1. catch multiple : gestion de différentes exceptions
Dans les programmes réels, un même bloc de code peut lever différents types d’exceptions. Par exemple, lors de la lecture d’un fichier, on peut obtenir aussi bien FileNotFoundException que IOException, et lors de l’analyse des données — également NumberFormatException. Pour traiter correctement chaque situation, Java permet d’enchaîner plusieurs blocs catch.
Syntaxe
try {
// opérations dangereuses
} catch (FileNotFoundException e) {
System.out.println("Fichier introuvable : " + e.getMessage());
} catch (IOException e) {
System.out.println("Erreur d’entrée/sortie : " + e.getMessage());
} catch (NumberFormatException e) {
System.out.println("Format de nombre incorrect : " + e.getMessage());
}
Point important :
Les blocs catch doivent aller du plus spécifique au plus général ! Si vous écrivez d’abord catch (Exception e), tous les autres blocs deviendront inatteignables et le compilateur signalera une erreur.
Pourquoi est-ce important ?
- Traitement spécifique : On peut réagir différemment selon l’erreur (par exemple, proposer de choisir un autre fichier ou de recommencer la saisie).
- Lisibilité : Le code devient plus clair — on voit quelles erreurs sont attendues et comment elles sont gérées.
2. catch avec plusieurs types (multi-catch)
Parfois, des exceptions différentes nécessitent le même traitement. Par exemple, vous souhaitez simplement afficher un message d’erreur ou la consigner dans les logs, qu’il s’agisse d’une erreur de lecture de fichier ou de conversion de nombre.
Depuis Java 7, la syntaxe multi-catch permet de regrouper plusieurs types d’exceptions dans un même bloc :
try {
// opération dangereuse
} catch (IOException | NumberFormatException e) {
System.out.println("Erreur lors du traitement du fichier ou du nombre : " + e.getMessage());
}
Comment ça fonctionne :
- Les types d’exceptions sont indiqués à l’aide d’une barre verticale (|).
- La variable e aura le type de la superclasse commune la plus générale (généralement Exception).
- À l’intérieur du bloc, il est impossible d’assigner une nouvelle valeur à la variable e — elle est automatiquement considérée comme final.
Exemple :
try {
BufferedReader reader = new BufferedReader(new FileReader("numbers.txt"));
String line = reader.readLine();
int number = Integer.parseInt(line);
System.out.println("Nombre : " + number);
reader.close();
} catch (IOException | NumberFormatException e) {
System.out.println("Erreur : " + e.getMessage());
}
3. Bonnes pratiques de gestion des exceptions
N’étouffez pas les exceptions
Mauvais :
try {
// quelque chose de dangereux
} catch (Exception e) {
// on ne fait rien !
}
Pourquoi est-ce mauvais ?
Un bloc catch vide « étouffe » l’erreur — vous perdez l’information sur la cause de l’échec et le programme devient impossible à déboguer.
Mieux : au minimum, affichez un message ou consignez l’erreur dans les logs.
catch (Exception e) {
e.printStackTrace();
}
Si vous ne pouvez pas gérer l’exception — propagez-la :
catch (IOException e) {
throw e; // ou throw new RuntimeException(e);
}
Levez des exceptions aussi spécifiques que possible
Si vous écrivez vos propres méthodes ou API, levez toujours des exceptions aussi concrètes que possible, et non simplement Exception ou RuntimeException. Cela rend votre code et votre interface plus clairs pour les autres développeurs.
Exemple :
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Fonds insuffisants");
}
// ...
}
N’utilisez pas les exceptions pour contrôler le flux du programme
Les exceptions sont destinées à traiter des situations exceptionnelles — c’est-à-dire des erreurs qui ne devraient pas se produire dans le déroulement normal du programme. Ne les utilisez pas pour la logique courante (par exemple, pour sortir d’une boucle ou vérifier des conditions).
Mauvais :
try {
while (true) {
String line = reader.readLine();
if (line == null) break;
// traitement de la ligne
}
} catch (Exception e) {
// utiliser une exception pour sortir de la boucle — mauvais !
}
Bien :
String line;
while ((line = reader.readLine()) != null) {
// traitement de la ligne
}
4. Exemples pratiques
Exemple : traiter différentes erreurs différemment
try {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
String line = reader.readLine();
int number = Integer.parseInt(line);
System.out.println("Nombre : " + number);
reader.close();
} catch (FileNotFoundException e) {
System.out.println("Fichier introuvable !");
} catch (IOException e) {
System.out.println("Erreur de lecture de fichier !");
} catch (NumberFormatException e) {
System.out.println("Le fichier ne contient pas de nombre !");
}
Exemple : multi-catch pour un traitement identique
try {
// quelque chose de dangereux
} catch (IOException | NumberFormatException e) {
System.out.println("Erreur : " + e.getMessage());
}
5. Points importants et erreurs courantes
Erreur n° 1 : Ordre incorrect des blocs catch. Les exceptions les plus spécifiques doivent venir d’abord, puis les générales. Sinon, l’exécution n’atteindra jamais le bloc le plus large.
Erreur n° 2 : Utiliser des types apparentés dans un multi-catch. Par exemple, catch (IOException | Exception e) ne se compilera pas, car IOException hérite de Exception.
Erreur n° 3 : Tentative de modifier la variable e dans un multi-catch. Dans ce cas, e est considérée comme final — on ne peut pas lui attribuer une nouvelle valeur.
Erreur n° 4 : Blocs catch vides. Ignorer les erreurs entraîne des bogues « silencieux ». À minima, affichez un message ou journalisez l’exception.
Erreur n° 5 : Capturer toutes les Exception indistinctement. Utiliser catch (Exception e) masque les problèmes réels et complique le débogage. Il vaut mieux ne capturer que les exceptions attendues.
GO TO FULL VERSION