Exceptions

1) Exemple sans exception

public double get( int i ) { return tab[i-1]; }
que retourner si mauvais indice ?

2) Définition

2.1. Une exception est un évènement exceptionnel qui peut survenir pendant le déroulement d'un programme et qui provoque le déroutement du flot d'instructions normal.
2.2. En java, une exception est un objet d'une sous-classe d'Exception et des exceptions de types différents peuvent être distinguées.
2.3. On peut créer ses propres exceptions et y ajouter de l'information.

3) Système de gestion des exceptions

3.1. "parallèle" au déroulement normal; lancer une exception et la rattraper ailleurs
3.2. Exemple
main()
{ ...
procA();
...
...
...
...
...
}
void procA()
{ ...
procB();
./.
ttt exception
...
...
}
void procB()
{ ...
...
int i=funcC();
./.
./.
./.
./.
}
int funcC()
{ ...
...
...
EXCEPTION!
./.
./.
return valeur;
}

funcC() lance une exception (donc instructions suivantes non exécutées) --> procB( )
procB() n'a rien prévu pour la traiter (donc propage l'exception) (donc instructions suivantes non exécutées) --> procA( )
procA() sait traiter l'exception et continue son exécution après le traitement de l'exception (mais quelques instructions non exécutées quand-même)
main() ne s'est aperçu de rien
si rien n'est prévu nulle part, le programme se termine avec un long message (StackTrace).

4) Avantages

4.1. séparer les instructions normales du traitement des erreurs
4.2. propager l'exception à la méthode appelante et ainsi de suite
4.3. différencier et regrouper des exceptions différentes grâce aux hiérarchies de classes (héritant de Exception)

5) Exceptions existant dans Java

5.1. Hiérarchie
       Object
          ^
      Throwable
     ^         ^
   Error   Exception
   | | |   | | | | ^
           | | | | RuntimeException
           | | | |   |  |  |  |  |
           1 2 3 ..  4  5  6  7  .. 
5.2. Error est un type d'erreur système "grave"; on ne peut rien faire, donc inutile d'essayer de les attraper et traiter.
(exemples: AssertionEr, VirtualMachineEr, OutOfMemoryEr, StackOverflowEr)
5.3. Exception est un type d'erreur qui peut être traitée; on a le choix de dire qu'une méthode la lance ou bien de l'attraper et traiter à l'intérieur.
(catch or specify, checked exceptions, outside JVM)
(exemples: CloneNotSupportedEx, AWTEx, IOEx, EOFEx, FileNotFoundEx)
5.4. RuntimeException est un type particulier d'exception qui correspond en général à une erreur du programmeur; on n'a donc pas obligation ni de la déclarer ni de l'attraper et traiter. Par contre, on a obligation de corriger son programme pour qu'elle n'arrive pas !
(unchecked exceptions, inside JVM)
(exemples: ArithmeticEx, ClassCastEx, NegativeArraySizeEx, NullPointerEx, IllegalArgumentEx, NumberFormatEx, IndexOutOfBoundsEx)
5.5. Les classes 1 2 ... correspondent aux exceptions déjà définies dans les nombreuses classes Java.

6) Traitement des exceptions lancées par le JDK

6.1. Exemple:
try { instructions } catch ( UneClasseException pObjetException ) { traitement }
(voir méthodes getStackTrace(), printStackTrace(), getMessage(), getLocalizedMessage(), toString())
6.2. S'il y a plusieurs exceptions possibles, on peut mettre successivement plusieurs catch après un seul try.
Attention! l'ordre est important (du particulier au général)
6.3. Si un traitement est commun à plusieurs exceptions héritant d'une même classe, écrire catch ( ClasseMereException objetException )
6.4. On sait quelle classe exception en regardant la javadoc
Exemple: Throws: UneClasseException
6.5. Si une méthode appelée lance une exception dont la classe n'hérite pas de RunTimeException, soit il faut entourer l'appel d'un try/catch, soit il faut déclarer qu'on lance l'exception
==> throws UneClasseException à la fin de la signature (plusieurs possibles)
6.6. On peut traiter partiellement et relancer l'exception dans le catch: throw e;
==> throws UneClasseException
6.7. Si un traitement doit être fait qu'une exception soit lancée ou pas, ajouter après le try/catch un bloc finally { traitement }
(si exception imprévue, ou return dans try ou catch)
Classe de démonstration du bloc finally (à essayer !)

7) Lancer des exceptions du JDK

7.1. Exemple: if (mauvais paramètre) throw new UneClasseException("...");
==> throws UneClasseException
7.2. Ne pas rattraper une exception dans la même méthode que celle où on l'a lancée; il vaut mieux
if (cond) { i1 } else { i2 } que
try { if (!cond) throw new UneClasseException(); i1 } catch ( UneClasseException e ) { i2 }

8) Créer ses propres exceptions

8.1. Créer une classe qui extends Exception ou une de ses sous-classes
8.2. Redéfinir éventuellement getMessage()
8.3. Ajouter éventuellement des attributs (donc constructeur), voire des méthodes

9) Les assertions

9.1. Programmation par contrat, sécurité : pré-condition, post-condition, pas d'invariant
9.2. assert condition : message;
équivalent à   if (!condition) throw new AssertionError(message);
mais comment les retirer ?
9.3. Pour autoriser les assertions :
-ea à la compilation (difficile en BlueJ, voir javac)