Exceptions
IFT1025: Programmation 2
Jian-Yun Nie
Concepts
• Erreur vs. Exception– Erreur: Un erreur logique impossible de réparer– Exception: un événement imprévu
• Laisser l’exception sans traiter (échec du programme)• Traiter l’exception (le programme continue après le traitement)
• Traitement d’exception– Un contrôle de sécurité
• Appel d’une méthode dans de bonnes conditions ?• Exécution de la méthode se déroule correctement ?• …• Sinon, quelles alternatives, correction ?
– Mécanisme de traitement: général (classe) pour faciliter les traitements
Échec d’un programme
• Impossibilité pour le système d’accomplir une tâche
• 2 raisons d’échec– Erreur logique dans l’implantation (la faute du
programmeur)– Impossibilité d’obtenir des ressources nécessaires
(e.g. fichier)
• Dans le cas d’erreur, pas réparable (seulement un message d’erreur)
• Mais pour la second classe: possible de traiter
Ressources nécessaires
• Matériel
• Système d’exploitation
• Fichiers
• Réseau
• Base de données
• Utilisateur (interaction)
Exception
• Apparition d’une situation anormale, détectable, qui conduit à l’échec du programme
• Possibilité pour un programme de détecter et traiter certaines exceptions pour éviter l’échec du programme
Exemplepublic class Lecture_mot { static BufferedReader input;
public static void main(String[] args) {
ouvrir_fichier("liste_mots");
traiter_fichier();
fermer_fichier(); }
// ouverture du fichier public static void ouvrir_fichier(String nom) { try {
input = new BufferedReader( new FileReader(nom));
}catch (IOException e) { System.err.println("Impossible d'ouvrir le fichier d'entree.\n" +
e.toString()); System.exit(1);}
} // ouvrir_fichier
Si on utilise juste cette ligne, et que "liste_mots" n’existe pas - une exception non traitée, le programme échoue
Possibilité de traiter l’exception ici, e.g. demander à l’utilisateur d’entrer un autre fichier
Message d’exception
…
catch (IOException e) {
System.err.println("Impossible d'ouvrir le fichier d'entree.\n" +
e.toString());
System.exit(1);
}
Message affiché:
Impossible d'ouvrir le fichier d'entree.
java.io.FileNotFoundException: liste_mots (No such file or directory)
Mécanisme général en Java
• Permet de détecter, signaler ou traiter une exception
• Non pour traiter des situations prévues
• N’est pas un mécanisme de contrôle pour le branchement d’un programme (if, …)– Mais plutôt un autre mécanisme qui contrôle
l’exécution
Mécanisme général• Exemples d’exemption
– Diviser par 0 – Accéder un tableau avec un index invalide
Méthode qui appelle:
…
Appel
…
Méthode appelée:
…
Normal
Exception
appel
Message d’exception
Suite normale
Traiter l’exception
Retour normal
Mécanisme général
• Deux mécanismes en parallèle– Traitement normal– Traitement d’exception (exception handler)
• Quand il y a une exception– Le traitement normal s’arrête– Le traitement d’exception prend le contrôle
Traitement d’exception en chaîne
• méthode_1 appelle méthode_2, qui appelle méthode 3
• Si méthode 3 génère une exception– Message d’exception est envoyé à méthode_2– Méthode_2 peut
• Traiter (attraper) l’exception• Relancer l’exception: le message d’exception sera envoyé à
méthode_1• …• Si une exception n’est traitée par aucune méthode qui appelle:
sortie du programme avec un message d’exception
Méthode_1 Méthode_2 Méthode_3
Exemple de transmission d’exception
Générer une exception
• Certaines exceptions standard sont reconnues– ArithmeticException: diviser par 0– ClassCastException: Casting d’un objet à une
mauvaise classe– EOFException: Lire après la fin d’un fichier– IllegalArgumentException: paramètres illégaux ou
inappropriés– …
• Quand une de ces exceptions est rencontrée, le système lance (throw) un message d’exception
Hiérarchie des classes d’exceptions
Attraper (catch) une exception• Attraper une exception pour la traiter
try {statements
: :} catch ( ExceptionClass1 object) {
statements :
:} catch (ExceptionClass2 object) {
statements : :} …
Bloc où une exception peut se
générer
Blocs pour attraper les exceptions
Exemple public static void ouvrir_fichier(String nom) { try {
input = new BufferedReader( new FileReader(nom));
}catch (IOException e) { System.err.println("Impossible d'ouvrir le fichier d'entree.\n" +
e.toString()); System.exit(1);}
}
Un autre exemplepublic void getSomeData () throws FileNotFoundException, SecurityException{
FileReader in;boolean success = false; //Data file openedint tryNumber = 0; //# of attempts to open datafileint delay = 5 * 1000; //wait in milli secswhile (!success) try {
tryNumber = tryNumber + 1;in = new FileReader(“DataFile”);success = true;…
} catch (SecurityException e) {if (tryNumber == 1)
thisThread.sleep(delay);else throw e;
}}
Exécution avec catch
• Si aucune exception est générée (thrown), les instructions dans catch ne sont pas exécutées
• Si une exception est générée, l’exception est comparée dans l’ordre avec les clauses de catch (ExceptionClass object)– Si la classe de l’exception match celle de catch:
• exécution des instruction de ce catch, • continue après le dernier catch (sauter les autres catches)
– Seulement le premier catch compatible avec l’exception est exécuté
• Important: Catch d’abord les sous-classes d’exception– Si aucun catch est compatible avec l’exception,
• l’exception n’est pas attrapée (non traitée)• transmise à la méthode qui appelle
Checked vs. Unchecked• Checked exception
– Vérifiée par le compilateur– Si le programme peut générer une telle exception, il doit
• Soit la traiter dans le programme• Soit la retransmettre à l’appelant (avec throws dans l’entête)
– Typiquement générée à cause de l’environnement– Exemple, IOException– public void getSomeData () throws FileNotFoundException,
SecurityException• Unchecked exception
– RuntimeException– Problème du programmeur (mauvaise utilisation d’une méthode,
d’un objet, …)– Le compilateur ne la vérifie pas– Si un programme peut générer une telle exception, le
programme n’a pas à la signaler dans l’entête– public int division(înt a, int b) {return a/b; }
Checked vs. Unchecked exception
Lancer une checked exception
• Signaler au compilateur qu’une méthode peut lancer une exception (non attrapée, non traitée)
public void methode() throws ExceptionClass• Exemple
public void skip () throws IOException {
String s;
s = input.readLine();
}
• Si une exception apparaît, transmise à l’appelant (caller)
Traitement partiel d’exceptionspublic void getSomeData () throws
FileNotFoundException, SecurityException{FileReader in;try { in = new FileReader (“DataFile”); …} catch (FileNotFoundException e) { //cleanup throw e; // throws it again to its caller}} catch (SecurityException e) { //cleanup throw e; // throws it again to its caller
}
finally
• Exécuter un bloc quel que soit l’exception try
{
statement
. . .
}
finally
{
statement
. . .
}
Exécuter finally même si le bloc try lance ne exception
finally• Souvent combiné avec catch
try{
statement . . . } catch (ExceptionClass exceptionObject){
statement . . .}finally{
statement . . .}
Même si une exception est attrapée, finally sera toujours exécuté
Utile pour s’assurer de certaine sécurité (cleanup)
Générer une exception explicitement• Un programme peut aussi générer une exception
public class BankAccount throws IllegalArgumentException{ public void withdraw(double amount) { if (amount > balance) { IllegalArgumentException exception = new IllegalArgumentException("Amount exceeds balance"); throw exception; } balance = balance - amount; } . . .}
• Général: throw exceptionObject; • Forcer la méthode qui appelle de traiter cette exception
Définir ses propres exceptions
• Les classes d’exception prédéfinies ne sont pas suffisamment explicites
• On a besoin de faire la différence entre les exceptions pour leurs traitements
• Définir une sous-classe d’exception
public class NoDataException extends Exception {public NoDataException () { super();}public NoDataException (String s) { super(s);}
}• Définir une hiérarchies de classes d’exception
constructeurs
Un autre exemple
class TemperatureException extends Exception {}
class TooColdException extends TemperatureException {}
class TooHotException extends TemperatureException {}
Classe Exception
• ConstructeursException() Constructs a new exception with null as its detail message.
Exception(String message) Constructs a new exception with the specified detail message.
Exception(String message, Throwable cause) Constructs a new exception with the specified detail message
and cause.
Exception(Throwable cause) Constructs a new exception with the specified cause and a detail
message of (cause==null ? null : cause.toString()) (which typically contains the class and detail message of cause).
Classe Throwable
• 4 constructeurs
• Thrwoable getCause()– Cause de cette exception (ou null)
• String getMessage(): – message envoyé par l’exception
• String toString()– Générer un message décrivant l’exception
• …
Penser Exception comme des classes / sous-classes
Une TooColdException est aussi une TempretureException, Exception, Throwable
Attention aux catches:
Catch une sous-classe avant une super-classe
Prévenir des erreurs
• Certaines erreurs peuvent être détectées ou éviter
• Tester la pré-conditon, post-condition ou l’invariant d’une méthode– Pré-condition: condition sous laquelle on l’appelle– Post-condition: condition après la méthode– Invariant: conditions devant être vérifiée tout au long
• Test sur pré-condition : facile (assert)• Test sur post-condition et invariant : plus difficile
assert
• assert booleanExpression ;• assert booleanExpression : expression
• Si la condition non satisfaite, AssertionError
• Exemple
//Interchange list.get(i) and list.get(j)// require 0 <= i, j < list.size() …private <Element> void interchange (
List<Element> list, int i, int j) {assert 0 <= i && i < list.size(): "precondition: illegal i";assert 0 <= j && j < list.size(): "precondition: illegal j";…
Alternative (public)
//Interchange list.get(i) and list.get(j)
// require 0 <= i, j < list.size() …
public <Element> void interchange (
List<Element> list, int i, int j)
{
if (0 <= i && i < list.size()) throw new IndexOutOfBoundsException("illegal i“);
if (0 <= j && j < list.size()) throw new IndexOutOfBoundsException("illegal j“);
…
Convention
• Méthode utilitaire private: assert• Méthode public: exception
– Pourquoi pas d’assert pour tester les paramètres ?• Ce test ne correspondent pas à la spécification de la
méthode public• Ne permettrait pas de générer un message d’exception
approprié
• Activer/Désactiver assertion:– Javac -enableassertions …– Javac -disableassertions …
Méthode private ou public
• Méthodes public:– Comportement observable de l’extérieur– défini par une spécification
• Méthode private– Méthode utilitaire pour faire un traitement
interne– N’est pas directement visible de l’extérieur– Non définie par une spécification
Exemple
• Définir une méthode qui fait retourne le plus petite valeur d’un tableau– Spécification:
• Accepter un tableau de nombres entiers• Retourner la plus petite valeur stockée• Cas spécial - tableau vide: un message
d’exception
– Entête
public int plusPetit(int [] a)
Implantation
• public int plusPetit(int [] a){
…return pp(a, 0);
}private int pp(int [] a, int ind){
…int p = pp(a, ind+1);if (p>a[ind]) return a[ind] else return p;
}
Utiliser Exception
Utiliser Assert