Vous êtes sur la page 1sur 9

2

Algorithmique et Notion d’exception


Programmation Orientée Objet
en Java
2e année – Chapitre 4 : Les exceptions
Les entrées-sorties
Version 20.0327

Vers les exceptions 3


Exceptions en Java 4

• Solutions possibles lorsqu’une erreur apparait À quoi servent les exceptions ?


• Ne rien faire
• Programmation par contrat : il fallait respecter le domaine de définition documenté • Des sources et types d’erreurs prévus par Java
• Mauvaise gestion des classes : accès hors tableau, objet non créé, …
• Écrire un message d’erreur à l’écran
• Mais le programme appelant ne « lit pas l’écran » ! • Erreur arithmétique : division par zéro, log d’un nombre négatif, …
• Renvoyer un code d’erreur à la place du résultat • Entrée utilisateur non valide : saisie d’un texte au lieu d’un nombre, …
• Mais il faut réussir à le « cacher » dans le type du résultat, ce qui peut interdire un résultat valide • Problème de périphérique : déconnexion Wi-Fi, bourrage papier, …
• Mettre à jour une variable globale indiquant le code d’erreur • Limitation physique : disque plein, …
• Par exemple un attribut de l’objet dans lequel se situe la méthode appelée • …
• Utiliser un mécanisme d’exception unifié et standardisé
• C’est un canal spécifique pour renvoyer une erreur
• Des sources et types d’erreurs ajoutés par le
• Cette solution évite chacun des défauts ci-dessus données programmeur

Opération
• Java propose en standard ou
le mécanisme de gestion d’exception Méthode

résultat ou exception
normal (erreur)
Exemples d’exceptions de Java 5 6

Exceptions déjà rencontrées


• Division par zéro • Accès hors tableau
static void main(String[] args) static void main(String[] args) {
{ int[] tab = {4, 0, -1};
int[] tab = {2, 1, 0, -1}; int i = 0;
for (int val : tab) { while (i <= tab.length) {
System.out.println(20/val); System.out.println(tab[i]);

}
}
}
i++;
Rattraper une exception
System.out.println("done");
}
pour éviter l’arrêt du programme
10 4
20 0
Exception in thread "main" -1
java.lang.ArithmeticException: Exception in thread "main“
/ by zero java.lang.ArrayIndexOutOfBounds
at Main.main(Main.java:7) Exception: 3
at Main.main(Main.java:6)

• L’exécution du programme est arrêtée à l’erreur

Traiter une exception 7


Bloc « try/catch » 8

Capturer et traiter des exceptions Plusieurs instructions en try et plusieurs catch


• Les blocs try{…} try {
… // Instructions susceptibles de générer une exception
• Permettent de délimiter une partie du programme dont les …
opérations et appels de méthodes sont susceptibles de générer } catch(Type1 e) { // Capture d’exceptions de type Type1 ou dérivé
… // Traitement de l’exception de Type1
des exceptions que l’on souhaite traiter. …
} catch(Type2 e) { // Capture d’exceptions de type Type2 ou dérivé
• Les clauses catch(TypeException t){…} … // Traitement de l’exception de Type 2

• Placées à la suite d’un bloc try, elles indiquent la réaction à une } catch(Type3 | Type4 e) { // Capture d’exceptions 3 et 4 ou dérivées
exception du type spécifié qui a stoppé défintivement l’exécution … // Traitement des exceptions de Type 3 et 4
du bloc try. }

static void main(String[] args) {


• Les blocs try contiennent généralement plusieurs instructions dont certaines
int[] tab = {2, 1, 0, -1};
try { sont susceptibles de générer des exceptions.
for (int val : tab) { • Ces instructions internes peuvent même contenir d’autres blocs try.
System.out.println(20/val);
} • Plusieurs clauses catch peuvent être associées à un bloc try.
} catch(ArithmeticException e) { • La première clause catch de bon type est exécutée, les autres sont ignorées.
System.out.println("Division par zéro"); • Donc l’ordre des clauses catch est important è respecter l’ordre d’héritage.
}
System.out.println("done"); • Il est possible de générer des exceptions dans le bloc d’une clause catch.
}
Capture des exceptions 9
Propagation des exceptions 10

Capture des exceptions (cas simple) Capture des exceptions (avec propagation)
static void main(String[] args) { 10 static void main(String[] args) { 10
int[] tab = {2, 1, 0, -1}; 20 int[] tab = {2, 1, 0, -1}; 20
2 try { Division par zéro 3 2 try { Division par zéro 3
for (int val : tab) { Done 4 for (int val : tab) { Done 4
1 System.out.println(20/val); 2 int res = division(20,val);
2
} System.out.println(res);
} 3catch(ArithmeticException e) { }
System.out.println( } 3catch(ArithmeticException e) {
"Division par zéro"); System.out.println(
} "Division par zéro");
4 System.out.println("Done"); }
} 4 System.out.println("Done");
}
Lorsqu’une exception survient Bloc try{…} non trouvé dans
1. L’exécution du programme est stoppée là où survient une exception
static int division(int a, la méthode division(). La
int b) { recherche de catch continue
2. On trouve le try responsable de l’appel conduisant à l’exception 1 return a/b; dans la méthode qui a appelé
} la méthode division(), etc.
• englobant directement l’instruction ayant provoqué l’exception
• ou sinon en remontant la chaîne des méthodes appelantes L’exception est propagée dans ce cas
3. Le catch approprié est exécuté pour traiter l’exception à elle remonte la chaîne d’appel jusqu’à trouver un try/catch qui la rattrape
4. Le programme suit son cours à la suite du bloc try/catch exécuté

Le bloc « finally » 11 12

Bloc optionnel finally{…}


• Un seul bloc finally{…} peut être placé après la liste des clauses catch.
Le code contenu dans ce bloc sera toujours exécuté, soit :
• Après l’exécution du bloc try{} si aucune exception n’est survenue.
• Après l’exécution d’une clause catch ayant rattrapé une exception.
• Avant la recherche d’un bloc try{} de niveau supérieur
• quand aucune clause catch de type approprié n’a été trouvée pour rattraper
une exception du bloc try{}.
• quand une exception a été lancée dans une clause catch. Produire une exception
d’un type déjà existant
try {
… // Code susceptible de lancer une exception

} catch(Type1 e) {
… // Traitement de l’exception de Type1

} finally {
… // Traitement exécuté quoi qu’il arrive
}
• Exemples d’utilisation : sauvegarder des données, libérer des ressources, …
Lancer une exception 13
Spécifier l’exception lancée 14

Une méthode peut lancer une exception La méthode doit annoncer (dans sa signature) qu’elle peut
lancer certains types d’exceptions
• ≈ un signalement d’erreur à la place du return
paramètres d’entrée
• Spécification des exceptions lancées par une méthode
• Si une méthode peut lancer une exception, cela doit être indiqué par une
clause throws ClassException après la liste des paramètres de cette
méthode. (Vérifié par le compilateur)
Méthode static int division(int a, int b)
throws Exception, ArithmeticException {
if (a%b != 0) {
résultat ou exception throw new Exception("Division non entière");
}
(return) (throw)
return a/b;
}
• Instruction pour lancer une exception : throw e; à Toutes les exceptions produites sont spécifiées, y compris celles lancées
• e est une instance d’une classe héritant de la classe Throwable dans d’autres méthodes appelées par la méthode.
• Exemple 1 : throw new Exception("Message d’erreur"); à Si plusieurs types d’exceptions peuvent être lancés par une méthode, on
les sépare par des virgules après le throws.
• Exemple 2 : throw new ArithmeticException("Division by 0");

Exemple 15
La classe Exception de Java 16

Propagation et capture des exceptions La classe Exception


static void main(String[] args) {
int[] tab = {2, 1, 3, 0}; Exception
for (int val : tab) {
- String message
2 try {
2
2 int res = division(20,val);
System.out.println(res); + Exception() // Constructeur par défaut
3 } catch(ArithmeticException e) { + Exception(String) // Constructeur avec un message d’erreur
System.out.println("Division par zéro");
3 } catch(Exception e) { + String getMessage() // Récupérer le message d’erreur
4 System.out.println(e.getMessage()); + void printStackTrace() // Afficher la liste des méthodes appelantes lors du throw
} …
}
}
static int division(int a, int b) Exemple
throws Exception, ArithmeticException { try { Division non entière
if (a%b != 0) { int res = division(20,3); java.lang.Exception: Division
1 throw new Exception("Division non entière"); } catch(Exception e) { non entière
} System.out.println(e.getMessage());
at Main.division(Main.java:17)
return a/b; e.printStackTrace();
} } at Main.main(Main.java:6)
10
20 Si une exception n’est jamais rattrapée, y compris dans la méthode main, elle
Division non entière
provoque l’arrêt du programme et la méthode printStackTrace() sera appelée.
Division par zéro
Les autres classes de Java 17 18

Les classes classiques autour des exceptions


Throwable

Erreur du programme Exception Error


Erreurs de la JVM

RuntimeException ... IOException Erreur d’entrée-sortie Nouveaux types d’exceptions


définis par le programmeur
... ArithmeticException NullPointerException FileNotFoundException ...

• RuntimeException (et Error) sont des exceptions techniques qui


sont « discrètes » dans le code Java car non vérifiées (unchecked) :
• partie throws facultative dans les déclarations des méthodes pouvant les lancer
• donc bloc try/catch facultatif dans les méthodes pouvant les recevoir

Les autres classes de Java 19


Définir une nouvelle exception 20

Les classes classiques autour des exceptions


Hériter de la classe Exception
Throwable
Exception
Erreur du programme Exception Error - String message
Erreurs de la JVM
+ Exception() // Constructeur par défaut
RuntimeException ... IOException Erreur d’entrée-sortie + Exception(String) // Constructeur avec un message d’erreur

... ArithmeticException NullPointerException FileNotFoundException ...


Exemple de définition de classe dérivée
• On peut créer ses propres classes d’exception
public class MonException extends Exception {
à en héritant de Exception public MonException() {super();}
public MonException(String msg) {super(msg);}
ou d’une de ses classes filles }
Intérêt des exceptions 21 22

Mais pourquoi faire tout ça ?


• Le mécanisme de gestion des exceptions permet :
• De transmettre explicitement une erreur
• throw pour une exception ou lieu de return pour un résultat standard

• De garantir son traitement dans un contexte qualifié de niveau supérieur Entrées-Sorties en Java :
• Le bloc catch{} compatible d’un bloc try{} supérieur dans les appels

• Et même de traiter différemment une erreur selon le contexte dans lequel


elle survient
lecture et écriture
• Quand un catch réagit à l’exception, dans un fichier texte
il peut en repropager une différente au niveau supérieur (par un throw ) et sur l’entrée standard
• D’alléger le code en regroupant dans un seul bloc catch{} le traitement
de toutes les erreurs de plusieurs lignes d’instructions

Définition d’entrées-sorties 23
Lecture de fichier 24

Ouverture et fermeture d’un fichier texte


• Classe FileReader
Les entrées-sorties • FileReader permet la lecture des caractères dans un fichier texte.
• La lecture s’effectue caractère par caractère : flux de caractères
= communications entre l’unité centrale et les périphériques
• Constructeur : FileReader fr = new FileReader("path/file.txt");
• Lance une FileNotFoundException si le fichier n’existe pas

• Entrée depuis : • Classe BufferedReader


• clavier, fichier sur disque dur, connexion réseau, capteurs, … • BufferedReader facilite la lecture d’un « flux de caractères »
le clavier est usuellement qualifié d’entrée standard • Lecture par paquets pour éviter des accès multiples au flux
• Constructeur : BufferedReader br = new BufferedReader(Reader);
• Sortie vers : • Lire une ligne : String s = br.readLine();
• écran, imprimante, fichier sur disque dur, connexion réseau, actionneurs, … • Lance une IOException en cas d’erreur de lecture
l’écran est usuellement qualifié de sortie standard
• Fermeture du fichier
• br.close() ou fr.close() ferment indifféremment le flux
à fournies en Java par les classes du package java.io • Permet de libérer le fichier pour une autre utilisation
• Lance une IOException en cas d’erreur de fermeture
Exemple de lecture de fichier 25
Exemple de lecture de fichier 26

Lecture et affichage du contenu d’un fichier


• Version 1 (trop simpliste) • Version 2 (complète)
try { BufferedReader br = null;
BufferedReader br try {
= new BufferedReader(new FileReader("path/file.txt")); br = new BufferedReader(new FileReader("path/file.txt"));
while (br.ready()) { // Tant qu’on peut encore lire des choses while (br.ready()) { // Tant qu’on peut encore lire des choses
System.out.println(br.readLine()); System.out.println(br.readLine());
} }
br.close(); } catch(FileNotFoundException e) { // Erreur du constructeur
} catch(FileNotFoundException e) { // Erreur du constructeur System.out.println(e.getMessage()); // (par exemple)
System.out.println(e.getMessage()); // (par exemple) } catch(IOException e) { // Erreur de readline
} catch(IOException e) { // Erreur de readline e.printStackTrace(); // (par exemple)
e.printStackTrace(); // (par exemple) } finally {
} if (br != null) {
try {
• Problème : fichier non fermé en cas d’erreur avant la fin br.close();
} catch(IOException e) { // Erreur de fermeture finale
• on pourrait ajouter close() dans toutes les branches possibles System.out.println(e.getMessage());
}
• plutôt utiliser le bloc finally à version 2 }
}

Exemple de lecture de fichier 27


Conversion des données lues 28

Interprétation des données lues


• Version 3 (avec raccourci try-with-resources) • Convertir les lignes lues (sous forme de String)
try (BufferedReader br • Texte lu (= String) à à convertir en données
= new BufferedReader(new FileReader("path/file.txt"))) {
while (br.ready()) { // Tant qu’on peut encore lire des choses • Exemple : texte "1234" à convertir en nombre entier de valeur 1234
System.out.println(br.readLine());
} • Exemple : texte "3.14159" à convertir en nombre réel de valeur 3.14159
} catch(FileNotFoundException e) { // Erreur du constructeur
System.out.println(e.getMessage()); // par exemple
} catch(IOException e) { // Erreur de readline
e.printStackTrace(); // par exemple • Utiliser les méthodes de conversion des classes
} visées
• Les ressources définies dans les parenthèses du try • nombres : int i = Integer.parseInt(String);
double d = Double.parseDouble(String);
• sont séparées par des point-virgules
Lance une NumberFormatException si le texte n’est pas valide
à on peut éventuellement en avoir plusieurs
• booléen : boolean b = Boolean.parseBoolean(String);
• implémentent l’interface AutoCloseable • …
à garantit que chacune a une méthode close(), qui sera appelée automatiquement
Lecture au clavier 29
Exemple de lecture au clavier 30

Lecture au clavier (l’entrée standard) Exemple de lecture au clavier (l’entrée standard)


• Classe InputStreamReader • Lecture d’une valeur entière
• Permet de passer d’un flux binaire d’octets à un flux de caractères try {
InputStreamReader isr = new InputStreamReader(System.in);
• Utilisation classique : lecture de caractères sur l’entrée standard clavier BufferedReader br = new BufferedReader(isr);
new InputStreamReader(System.in); String str = br.readLine();
int value = Integer.parseInt(str);
• Combiné avec un BufferedReader : lecture par lignes } catch(IOException | NumberFormatException e) {
System.out.println(e.getMessage());
new BufferedReader(new InputStreamReader(System.in));
}

Découpage des lignes lues 31


Écriture de fichier 32

Lecture dans un fichier texte Écriture dans un fichier texte


• Méthode utile : split(regex) de String • Classe FileWriter
• Permet de diviser une chaîne de caractères en sous-parties • Constructeur : FileWriter(String path, boolean append)
• Le paramètre append permet de choisir ou non d’écrire à la suite du
• Le paramètre regex permet d’indiquer la séparation utilisée
contenu existant.
• Exemple • Lance une IOException si l’ouverture est impossible (droit d’écriture,
fichier déjà ouvert, …)
String s = "To infinity and beyond (Buzz Lightyear)";
System.out.println(s); • Méthode write(String str) permet d’écrire une chaine de caractères
String[] segments = s.split(" "); dans le fichier
for (int i = 0; i<segments.length; i++) { • Le contenu du fichier est réellement modifié sur le disque dur
System.out.println(i + " - " + segments[i]);
} • en appelant explicitement la méthode flush()
• ou implicitement en fermant le fichier avec la méthode close()
To infinity and beyond (Buzz Lightyear)
0 – To
1 – infinity
2 – and
3 – beyond
4 – (Buzz
5 – Lightyear)
Exercice 33
Exercice 34

Énoncé Solution
• Écrire une méthode static int askInt() qui retourne
static
une valeur entière saisie au clavier par l’utilisateur. boolean
• Quand la valeur saisie n’est pas un entier, un message d’erreur doit être int res
InputStr
affiché puis on recommence la saisie. Buffered
while
try
String
res
corre
} catch
Syste
}
}
return
}

Vous aimerez peut-être aussi