f. voisin : introduction à java 1 introduction à java - les exceptions - frédéric voisin fiifo -...

24
F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

Upload: alison-metais

Post on 03-Apr-2015

131 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 1

Introduction à Java

- les exceptions -

Frédéric VOISIN

FIIFO - « Remise à Niveau »

Page 2: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 2

Pourquoi des « exceptions » ?

Gérer des « situations exceptionnelles » Cas d’erreurs liées

à l’environnement (JVM) à des erreurs de programmation (référence nulle, index de tableaux) à une application/classe particulière (next() sur un itérateur épuisé)

… ou tout autre événement impliquant une rupture (partielle) du déroulement normal du programme

Mécanisme utile si on ne sait pas que faire à l’endroit où le problème est découvert (on ne peut

que le signaler à l’appelant, et autrement que textuellement !)

Si on ne sait pas forcément à quel niveau le problème pourra être traité (par défaut on doit propager l’alerte)

Page 3: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 3

Pourquoi des « exceptions » ? (suite)

Signaler explicitement des cas « exceptionnels » Eviter de procéder par « retour de valeur particulière » qui ne sont pas toujours

testées par l’appelant Eviter que les cas « erronés » soient ignorés : une exception non traitée

interrompt le programme Eviter d’obscurcir les cas « normaux » avec les situations « exceptionnelles »

(tester toute référence à null avant usage ? Conversions à partir de Object ? )

Autoriser des traitements de rattrapage arbitrairement complexes

Autoriser des traitements sélectifs : chaque méthode décide quels cas exceptionnels elle sait traiter et quels cas relèvent des méthodes appelantes.

Page 4: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 4

« Gérer » une exception ?

Signaler une situation exceptionnelle (« lever une exception »)throw instance d’exception ;

Se protéger vis-à-vis d’une situation exceptionnelle, si on est capable de la prendre en compte (rattraper une exception) !

try { liste d’instructions } // bloc protégé !

catch (ClasseException1 variable){ traitement correctif 1 }catch (ClasseException2 variable){ traitement correctif 2 }…

Propager (explicitement ou implicitement) une exception qu’on ne sait pas traiter complètement

Souvent on est amené à combiner traitement local + propagation à l’appelant (sous le même nom d’exception ou un autre !)

Page 5: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 5

Qu’est-ce qu’une (classe) d’exception ?

Une exception = une instance d’une classe membre d’une hiérarchie (extensible) de classes, de racine Throwable

Error, Exception, RunTimeException, IOException, …

Une classe d’exception est une classe « ordinaire », avec éventuellement des constructeurs, des attributs, des méthodes

Méthodes héritées de Throwable : getMessage() toString() printStackTrace() // historique de propagation fillInStackTrace()

+ une description du contexte d’exécution au moment de la levée de l’exception

Les règles de typage classiques (classe/sous-classes) s’appliquent ! On peut donc organiser ses exceptions en hiérarchie

Page 6: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 6

class java.lang.Throwable sous-classe directe de Object !

class java.lang.Error Difficilement rattrapables !

class java.lang.VirtualMachineError

class java.lang.OutOfMemoryError…

class java.lang.Exceptionclass java.lang.RuntimeExceptiontrop fréquentes pour qu’on oblige

class java.lang.ArithmeticException à les signaler à l’avance !

class java.lang.ClassCastException elles peuvent donc survenir partout…

class java.lang.IllegalArgumentException

class java.lang.IllegalThreadStateException

class java.lang.NumberFormatException

class java.lang.IndexOutOfBoundsException

class java.lang.ArrayIndexOutOfBoundsException

class java.lang.StringIndexOutOfBoundsException

class java.lang.NegativeArraySizeException

class java.lang.NullPointerException

class java.util.NoSuchElementException

class java.io.IOException (voir transparent suivant !)

Ici prochainement, vos exceptions !

Page 7: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 7

La sous-hiérarchie « IOException »

class java.lang.Exception class java.io.IOException // dans le paquetage java.io

class java.io.EOFException class java.io.FileNotFoundException class java.io.InterruptedIOException class java.io.ObjectStreamException

class java.io.InvalidClassException class java.io.InvalidObjectException class java.io.NotActiveException class java.io.NotSerializableException // à voir ultérieurement class java.io.OptionalDataException class java.io.StreamCorruptedException class java.io.WriteAbortedException

Pour gérer toute exception liée aux E/S il suffit de rattraper IOException

On peut traiter de façon spécifique des cas particuliers (ex. les exceptions

FileNotFoundException et EOFException).

Page 8: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 8

Spécification des exceptions

Une méthode doit déclarer explicitement les exceptions qu’elle est susceptible de lever :

public void f(…) throws E1, E2 { … } le corps de f ne peut lever que les exceptions de classe E1 ou E2

f doit se préoccuper des exceptions levées par les méthodes qu’elle appelle soit en les rattrapant soit en les propageant (et en le déclarant dans son en-tête)

L’appelant de f sait donc contre quelles exceptions se prémunir… Toute redéfinition de f dans les sous-classes devra respecter ce profil …mais

rien n’empêche de lever une exception plus spécifique (sous-classe)

Exemple: toute redéfinition de equals(Object O) ne peut lever que des instances (au sens large) de RuntimeException ou Error.

La règle s’applique aussi à la méthode main !

Page 9: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 9

Spécification des exceptions (exemple)

import java.util.Calendar;

public class RnDate {

public RnDate(int year, int quantieme) throws ErreurDate { … refuse RnDate(2003, 366) ou RnDate(2003, -1) !

}

// KO : l’exception n’est ni rattrapée, ni « déclarée »

// Rejeté, même si en pratique l’exception ne peut pas se produire !

public static RnDate aujourdhui() {

Calendar date = Calendar.getInstance();

return new RnDate(date.get(Calendar.YEAR),

date.get(Calendar.DAY_OF_YEAR));

}

}

Page 10: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 10

Spécification des exceptions (suite)

A titre dérogatoire, il est facultatif de spécifier la levée des exceptions des hiérarchies Error et RunTimeException

public void f(…) { …} ne peut donc lever/propager que des exceptions de classe Error ou

RunTimeException, difficilement rattrapables

public void f(…) throws Throwable { …} peut lever des exceptions arbitraires mais laisse une (trop) lourde charge à ses

appelants et est peu coopérative

Page 11: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 11

Levée, récupération et propagation d’exceptions

Une rupture du déroulement normal du programme… :

arrêt du déroulement normal du programme pour rechercher dynamiquement un traite-exception adapté

Ce traitement remplace le traitement normalement effectué, sans possibilité de retour…

Levée implicite par la JVM ou une classe existante:String[] tab = new String[0];

Integer I; … ; System.out.println(Integer.intValue(I));

new Arraylist().iterator().next();

Levée explicite par le code du programmeur:throw new MonException();

Page 12: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 12

try { f1(); … fN(); } // bloc protégé

catch (E1 v) { instructions } // des traites-exceptions (« handlers »)…

catch (Ep v) { instructions } // … en nombre quelconque

Les catch sont examinés dans l’ordre jusqu’à trouver le premier qui correspond (modulo le sous-typage). Le compilateur vérifie que tout catch est accessible.

Le traite-exception retenu remplace la fin du traitement du bloc try et continue à sa suite, avec les mêmes contraintes (type d’une valeur retournée, exceptions levées, etc.)

A vous de conserver suffisamment d’information sur le contexte pour traiter l’exception (quel appel fi() a provoqué l’exception ?)

Levée, récupération et propagation d’exceptions

Page 13: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 13

Récupération d’exceptions (suite)

Un catch peut lui-même lever une exceptionla même : ou une autre :

catch (Exception e) { catch (Exception e) {

traitement local traitement local

throw e; throw newMonException();

} }

mais une exception levée dans un catch n’est jamais rattrapable dans le même bloc try/catch.

Les try/catch peuvent englober d’autres blocs try/catch

En l’absence de catch adapté, propagation automatique de l’exception au bloc englobant (où la même recherche de bloc catch aura lieu)

Page 14: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 14

Récupération d’exceptions (fin)

Attention à la portée des try/catch :

f(Iterator it) { f(Iterator it) {

try { while (true)

while (true) try {

it.next(); it.next();

} catch (…) { … } } catch (…) { … }

} }

Page 15: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 15

Levée, récupération et propagation d’exceptions

Recherche, selon l’imbrication des try/catch, d’un traite-exception adapté Si on en trouve un : l’exécution continue à partir de ce point de la méthode Sinon, l’exécution de la méthode est interrompue et l’exception est signalée chez

l’appelant, au point d’appel…

On remonte donc dynamiquement la chaîne d’appels de méthodes jusqu’à éventuellement la méthode main initiale

Si l’exception n’est jamais rattrapée, il y a interruption du programme…

On ne rattrape pas si on ne sait pas quoi en faire…

On ne rattrape pas si c’est juste pour propager !

Page 16: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 16

Exceptions et constructeurs

Attention aux exceptions dans les constructeurs : Dans quel état laisse-t-on l’instance concernée (initialisation partielle) ?

Qu’est-ce que l’utilisateur pourra faire avec l’instance concernée ? Une exception levée dans un constructeur n’est jamais récupérable dans un

autre constructeurpublic RnDate(int year, int quant) throws ErreurDate { …

}

public RnDate() { this(year, today); // Comment la rattraper ?

} Même problème pour la liaison constructeur sous-classe/super-classe ! Le constructeur de la sous-classe peut avoir des exceptions différentes…

Page 17: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 17

La clause « finally »

try {

instructions

} catch (Exception1 e1) { …

} … … … // traites-exceptions optionnels

} catch (ExceptionN eN) {

} finally { instructions } // clause optionnelle

Rôle : garantir qu’un fragment de code est exécuté dans tous les cas, normaux ou avec des exceptions, rattrapées ou non !

Précautions d’usage : attention aux doubles traitements attention à ne pas lever d’exceptions dans le bloc finally !

Page 18: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 18

La clause « finally » : exemple

class MonException extends Exception {}

public class TestFinally { // adapté de B. Eckel: "Thinking in Java" public static void main(String[] args) {

int count = 0;

while (true)

try { if (count == 0) { count++; throw new MonException(); }

else if (count == 2)

throw new NullPointerException();

else { count++; System.out.println("Cas normal"); }

} catch (MonException e) {

System.out.println("Dans le traite-exception");

} finally { System.out.println("Dans le bloc finally");}

}

}

Question : quels sont les affichages réalisés ?

Page 19: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 19

La clause « finally » dans les boucles …

class MonException extends Exception {}

public class TestFinally2 { // adapte de B. Eckel: "Thinking in Java" public static void main(String[] args) {

int count = 0;

while (count < 10)

try { count++;

if (count % 2 == 0) continue;

else if (count == 7) break;

else System.out.println("Cas normal: " + count);

} finally { // Exécuté dans les 3 cas ... System.out.println("Dans le bloc finally: " + count);

}

}

}

Page 20: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 20

Eléments méthodologiques

On anticipe (i.e. on évite l’exception par un test explicite) ou on rattrape l’exception ?

Privilégier la correction du code et sa lisibilité

Une partie intégrante de la conception d’une classe

Qui lève quoi ? Aussi important que les types des paramètres !

Quel niveau de détail :

quelle interface (attributs, méthodes) ?

Quelle hiérarchie dans les exceptions ?

Page 21: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 21

Eléments méthodologiques : qui rattrape quoi ?

Idéalement : on ne rattrape une exception que si on sait quoi en faire. Halte aux rattrapages abusifs et aux messages d’erreur intempestifs !

Exemple: une pile d’éléments de capacité bornée est pleine.

L’utilisateur essaie d’empiler un nouvel élément. Vous faites quoi ?

En phase de mise au point : il vaut mieux ne pas rattraper les exceptions qui ne devraient pas se produire (=> facilite la mise au point grâce à la trace de propagation)

En production: on peut préférer un code plus « robuste » : on rattrape, à condition de savoir comment repartir du bon pied !

Page 22: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 22

Eléments méthodologiques : qui rattrape quoi ? (suite)

Il est courant de rattraper une exception pour en lever une autre à la place (éventuellement après un traitement local)

public RendezVous(RnDate d, int q, String s, Person p) throws ErreurRendezVous {

if (q < 1) throw new ErreurRendezVous ("erreurDurée");

try { this.deb = d; this.raison = s, this.qui = p; this.fin = new RnDate(d.annee(), d.quantieme() +

q);// OK ? } catch (ErreurDate e) {

p.prevenir("pas pendant le reveillon"); throw new ErreurRendezVous ("erreurAnnée");

}

Il reste des éléments de choix : une ou plusieurs exception pour les rendez-vous ? Quel rapport hiérarchique entre les exceptions des rendez-vous, intervalles et dates ?

Page 23: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 23

Eléments méthodologiques (fin)

Qu’est-ce qu’un cas exceptionnel ?

Exemple: la méthode add(Object O) de l’interface Collection : que se passe-t-il si on ajoute un élément ?

Certaines collections admettent les doubles (ArrayList) D’autres collections n’ont jamais de doubles (TreeSet) Certaines collections ont des contraintes supplémentaires

TreeSet : ne traite que les éléments munis d’une (même) relation d’ordre d’autres refusent d’ajouter null. D’autres enfin refusent d’implémenter add (ou remove)

Toutes doivent être vues comme des sous-classes de Collection. Leurs versions de add doit se faire à profil d’exception constant.

Quelles exceptions prévoyez-vous ? Pour quels cas de figure ?

Page 24: F. Voisin : Introduction à Java 1 Introduction à Java - les exceptions - Frédéric VOISIN FIIFO - « Remise à Niveau »

F. Voisin : Introduction à Java 24

Eléments méthodologiques : Exemple (fin)

Un garde-fou à garantir :

après C.add(e), si l’appel de méthode s’est bien passé, e doit être dans C !

Il n’est pas « exceptionnel » d’ajouter un élément à une collection qui le contient : add renvoie true si l’ajout est possible et C n’a pas été modifiée add renvoie false si l’ajout est possible et C n’a pas été modifiée add lève une exception si l’ajout est impossible :

UnsupportedOperationException pour celles qui n’implémentent pas add

ClassCastException pour celles qui ont des contraintes « de type »

IllegalArgumentException pour d’autres contraintes sur les éléments

Ces trois classes d’exception sont classées dans RuntimeException pour ne pas avoir à être spécifiées explicitement.

On peut donc jouer sur la valeur de retour et/ou sur la levée d’exception !