Accueil > Programmer avec Java >
Gérer les exceptions avec try et catch
Survol et attentes
Définitions
- Entrée invalide
- une entrée qui ne correspond pas à une gamme de valeurs acceptables.
- Exception
- un Ă©vĂ©nement imprĂ©vu qui cause le plantage dâun programme sâil nâest pas gĂ©rĂ©. Java inclut une classe
Exceptionqui permet de gĂ©rer ces Ă©vĂ©nements en fournissant des informations sur lâerreur qui sâest produite. tryetcatch- blocs de code utilisĂ©s pour gĂ©rer les exceptions en Java. Le bloc
trycontient le code qui pourrait gĂ©nĂ©rer une exception, et le bloccatchcontient le code qui gĂšre lâexception si elle se produit. throws- un mot-clĂ© utilisĂ© dans la signature dâune mĂ©thode pour indiquer quâelle utilise du code qui peut gĂ©nĂ©rer une exception et ne le gĂšre pas. La mĂ©thode passe ainsi la responsabilitĂ© de gĂ©rer lâexception Ă la mĂ©thode appelante.
- Responsabilité unique
- principe de conception de logiciel qui stipule quâune classe ou une mĂ©thode devrait ĂȘtre responsable dâune seule tĂąche.
Objectifs dâapprentissage
Ă la fin de cette leçon vous devrez ĂȘtre en mesure de :
- Identifier les exceptions les plus communes en Java.
- Savoir quâelles entrĂ©es peuvent causer des exceptions et les distinguer de celles qui sont invalides pour dâautres raisons.
- Comprendre la structure dâun bloc
tryetcatchpour gérer les exceptions.
CritĂšres de succĂšs
- Je peux gérer des cas qui causeraient autrement un plantage du programme en utilisant des blocs
tryetcatch.
Responsabilité unique
En gĂ©nie logicielle, il y a un principe qui sâappelle la responsabilitĂ© unique. Ce principe nous dit que chaque mĂ©thode doit ĂȘtre responsable dâune seule chose. Câest une des raisons pourquoi nous brisons nos algorithmes en mĂ©thodes plus petites : cela limite la responsabilitĂ© de main Ă lâorganisation globale des opĂ©rations et permet Ă chaque mĂ©thode dâavoir un objectif clair.
Si on utilise du code qui peut générer une exception, on a deux choix :
- ajouter une déclaration
throws ExceptionĂ la signature de la mĂ©thode pour passer la gestion de lâexception Ă la mĂ©thode appelante, ou - utiliser un bloc
tryetcatchpour gĂ©rer lâexception dans la mĂ©thode directement.
La deuxiĂšme option est prĂ©fĂ©rable selon le principe de responsabilitĂ© unique, car la mĂ©thode gĂšre les problĂšmes potentiels avec le code quâil utilise pour accomplir sa tĂąche, et les autres mĂ©thodes nâont pas besoin de sâen soucier : elles peuvent se concentrer sur leur propre tĂąche.
Bloc try et catch pour des entrées invalides
Le bloc try contient le code qui peut lancer une exception, et le bloc catch contient le code Ă faire si une exception est lancĂ©e. Voici la structure de base dâun bloc try et catch :
try {
// code qui pourrait lancer une exception
} catch (Exception e) {
// code à exécuter si une exception est lancée
}
Voici un exemple de code1 qui lance une exception si lâutilisateur entre un texte qui ne peut pas ĂȘtre converti en un nombre entier. Dans cet exemple, on ne laisse pas le programme planter, mais on demande Ă lâutilisateur de rĂ©essayer :
Fichier:
ExceptionExample.java
import java.util.*;
Scanner input = new Scanner(System.in);
int getInt(String prompt) {
// tentatives infinies jusqu'Ă ce que tout dans le try fonctionne
while (true) {
try {
System.out.print(prompt);
int number = input.nextInt(); // peut planter
return number; // quitte la méthode si tout va bien
} catch (Exception e) { // si ça plante
System.out.println(" Entrée invalide");
input.next(); // vide l'entrée invalide du Scanner
}
}
}
void main() {
int age = getInt("Entrez votre ùge : "); // pas besoin de savoir que ça peut planter
System.out.println("Vous avez soumis un Ăąge de : " + age);
}
Notez que dans main on veut simplement obtenir un nombre entier et lâutiliser. Cela est possible parce que la mĂ©thode getInt gĂšre les exceptions qui pourraient survenir lors de la conversion de lâentrĂ©e utilisateur en un nombre entier. Ainsi, chaque mĂ©thode sâoccupe de sa propre responsabilitĂ© et nâa pas besoin de connaĂźtre les dĂ©tails internes des autres mĂ©thodes. Câest un bon exemple de la responsabilitĂ© unique.
Voici une autre version de main 1 pour ce mĂȘme problĂšme, mais dans ce cas-ci, main gĂšre une autre sorte dâentrĂ©e invalide : une entrĂ©e qui nâest pas un Ăąge valide. Ce type dâerreur ne cause pas dâexception, mais pourrait causer des erreurs de logique dans le programme.
void main() {
int age = getInt("Entrez votre Ăąge : ");
if (age < 0) { // gérer une valeur logiquement invalide
System.out.println("Ăge invalide");
} else {
System.out.println("Vous avez soumis un Ăąge de : " + age);
}
}
Bloc try et catch pour des ressources comme des fichiers
Nous étudions les fichiers en plus de détail dans la derniÚre section de cette unité
Si le programme gĂ©nĂšre une exception lors de lâutilisation dâune ressource comme un fichier, il est important de fermer la ressource avant de quitter le programme. Pour cela, on utilise une dĂ©claration try avec une ressource. Dans cette version de la structure, la ressource est dĂ©clarĂ©e dans les parenthĂšses aprĂšs le mot-clĂ© try. La ressource est automatiquement fermĂ©e par Java Ă la fin du bloc try, mĂȘme si une exception est lancĂ©e.
Voici la structure dâune dĂ©claration try-catch quand le plantage est liĂ© Ă la ressource utilisĂ©e :
try ( déclaration de la ressource qui peut planter ) {
// code à exécuter avec la ressource si ça ne plante pas
} catch (Exception e) {
// code à exécuter si ça plante
}
Voici un exemple oĂč la ressource qui peut planter est un FileWriter pour Ă©crire dans un fichier.
void writeMessageToFile(String message) {
try (FileWriter output = new FileWriter("./data/output.txt")) {
output.write(message);
} catch (Exception e) {
System.out.println("Chemin de fichier invalide");
}
}
Voici un deuxiĂšme exemple oĂč la ressource qui peut planter est lâobjet File quâon passe au Scanner pour extraire son contenu.
String getFileContents(Locale decimalFormat) {
try (Scanner fileReader = new Scanner(new File("./data/input.txt"))) {
fileReader.useLocale(decimalFormat);
fileReader.useDelimiter("\\Z"); // next() s'arrĂȘte au caractĂšre de fin de fichier
return fileReader.next();
} catch (Exception e) {
System.out.println("Fichier introuvable");
return null; // quittez la méthode avec une référence `null` pour le String
}
}
Notez que dans ces deux exemples, on doit déclarer et initialiser la ressource plantable entre des parenthÚses aprÚs le mot-clé try.
Exceptions spécifiques
Pour ce cours, câest tout Ă fait normal dâutiliser Exception - la plus gĂ©nĂ©rale de toutes les exceptions - comme type dâexception dans le bloc catch. Mais en situation de production logicielle, câest important de dĂ©clarer lâexception spĂ©cifique qui peut survenir dans le bloc catch.
Par exemple :
- Dans le cas dâentrĂ©e invalide, le type dâexception qui est lancĂ©e est
InputMismatchException(avec les mĂ©thodes de Scanner nextInt et nextDouble) ouNumberFormatException(si on utilise plutĂŽt Integer.parseInt(input.next()) ou Double.parseDouble(input.next())). Ce sont des exceptions pour les erreurs de conversion de chaĂźnes de caractĂšres en nombres. - Dans le cas de la lecture ou lâĂ©criture de fichiers, lâexception est
IOException.
Utiliser une exception spĂ©cifique permet de gĂ©rer les exceptions de maniĂšre plus prĂ©cise. En fait, cette structure nous permet de dĂ©clarer un bloc catch pour chaque type dâexception qui peut survenir. Le premier bloc catch qui correspond Ă lâexception lancĂ©e est celui qui est exĂ©cutĂ©, comme une cascade if-else if, alors câest important de les mettre dans lâordre du plus spĂ©cifique (p. ex. IOException) au plus gĂ©nĂ©ral (Exception).
Exercices
đ Tester la comprĂ©hension
aucun quiz de vérification des concepts ici encore
đ ïž Pratique
Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices
- Créez une copie de
ExceptionExample.javaet le tester. - Ajoutez une méthode
double getDouble(String prompt)qui fonctionne de la mĂȘme maniĂšre quegetInt, mais pour les nombres Ă virgule flottante et ajouter une utilisation de cette mĂ©thode dansmain. - Remplacez
System.out.println("EntrĂ©e invalide");dans les blocs catch avece.printStackTrace();pour voir le message dâerreur complet sans toutefois faire planter le programme. Notez le type dâexception qui est lancĂ©e (celui qui sâaffiche en premier dans le message dâerreur).