Différence entre try, catch et throw en Java
Quatre mots-clés forment le socle de la gestion d'erreurs en Java : try, catch, throw et throws. Ils ont des rôles très différents mais sont souvent confondus. Ce guide les clarifie un par un.
try : délimiter une zone à risque
Le bloc try entoure du code susceptible de lever une exception :
try {
int resultat = 10 / 0; // lève ArithmeticException
System.out.println(resultat);
}
Un try doit obligatoirement être suivi d'au moins un catch ou un finally, sinon le compilateur refuse.
catch : intercepter une exception
Le bloc catch capture une exception lancée dans le try correspondant :
try {
int resultat = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Division par zéro : " + e.getMessage());
}
On peut chaîner plusieurs catch du plus spécifique au plus général :
try {
lireFichier("/etc/config");
} catch (FileNotFoundException e) {
System.out.println("Fichier absent");
} catch (IOException e) {
System.out.println("Erreur I/O : " + e.getMessage());
} catch (Exception e) {
System.out.println("Erreur inattendue");
}
Depuis Java 7, le multi-catch permet de traiter plusieurs types dans un seul bloc :
try {
...
} catch (IOException | SQLException e) {
logger.error("Erreur I/O ou base de données", e);
}
throw : lancer une exception
Le mot-clé throw sert à émettre une exception manuellement :
public void retirer(int montant) {
if (montant <= 0) {
throw new IllegalArgumentException("Le montant doit être positif");
}
if (montant > solde) {
throw new IllegalStateException("Solde insuffisant");
}
solde -= montant;
}
Usage typique : validation des paramètres d'entrée, invariants métier, cas impossibles.
throws : déclarer les exceptions propagées
Contrairement à throw, throws apparaît dans la signature de méthode. Il annonce les exceptions vérifiées que la méthode peut propager à son appelant :
public String lireFichier(String chemin) throws IOException {
return Files.readString(Paths.get(chemin));
}
Quiconque appelle lireFichier devra soit l'entourer d'un try/catch, soit déclarer lui aussi throws IOException.
Différence clé : checked vs unchecked
| Type | Classe racine | throws obligatoire ? | Exemple |
|---|---|---|---|
| Checked | Exception | Oui | IOException, SQLException |
| Unchecked | RuntimeException | Non | NullPointerException, IllegalArgumentException |
| Error | Error | Non | OutOfMemoryError |
Les checked exceptions forcent le compilateur à exiger un traitement. Les unchecked sont habituellement le signe d'un bug ou d'un état invalide et ne sont pas captives du throws.
Exemple complet
public class Compte {
private double solde;
public void retirer(double montant) throws SoldeInsuffisantException {
if (montant <= 0) {
throw new IllegalArgumentException("Montant invalide");
}
if (montant > solde) {
throw new SoldeInsuffisantException("Solde : " + solde);
}
solde -= montant;
}
}
public static void main(String[] args) {
Compte c = new Compte();
try {
c.retirer(100);
} catch (SoldeInsuffisantException e) {
System.err.println("Retrait refusé : " + e.getMessage());
} catch (IllegalArgumentException e) {
System.err.println("Paramètre invalide : " + e.getMessage());
}
}
finally : toujours exécuté
Un bloc finally s'exécute que l'exception soit levée ou non, très utile pour fermer des ressources :
FileInputStream in = null;
try {
in = new FileInputStream("data.txt");
// ...
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) try { in.close(); } catch (IOException ignore) {}
}
Cette forme est aujourd'hui dépassée : préférez try-with-resources qui appelle close() automatiquement :
try (FileInputStream in = new FileInputStream("data.txt")) {
// ...
} catch (IOException e) {
e.printStackTrace();
}
Bonnes pratiques
- Ne jamais attraper
Throwable: cela inclutOutOfMemoryErrorqu'on ne peut rarement gérer. - Ne pas attraper si on ne sait pas quoi faire — laissez l'exception remonter jusqu'à un endroit qui sait réagir.
- Conserver la cause quand vous relancez :
throw new MonException("msg", e); - Préférer les RuntimeException pour les erreurs programmeur (argument invalide, état impossible).
- Utiliser
try-with-resourcespour tout objet qui implémenteAutoCloseable.
Résumé
try: délimite une zone où une exception peut survenir.catch: intercepte et traite une exception.throw: lance manuellement une exception.throws: déclare les exceptions vérifiées qu'une méthode peut laisser remonter.
Ces quatre mots-clés forment la base ; combinés correctement, ils produisent un code Java robuste, lisible et clair sur sa gestion des erreurs.