Le langage de programmation Java utilise des exceptions pour gérer les erreurs et autres événements exceptionnels.
Une exception est un événement qui se produit pendant l'exécution d'un programme et qui perturbe le déroulement normal des instructions. En Java, les exceptions sont levées explicitement, et l'action de lever une exception s'appelle lancer une exception. L'action de gérer une exception s'appelle capturer une exception.
En Java, toutes les exceptions sont des sous-classes de la classe Exception, qui est elle-même une sous-classe de Throwable.
Java distingue deux types d'exceptions :
Les exceptions vérifiées sont des conditions exceptionnelles qu'une application doit anticiper et dont elle doit pouvoir se remettre.
Un exemple d'exception vérifiée est FileNotFoundException, qui se produit quand une méthode essaie de lire un fichier qui n'existe pas.
Ce type d'exception est vérifié à la compilation : les méthodes qui lancent des exceptions vérifiées doivent l'indiquer dans leur signature, et le code qui appelle une méthode susceptible de lancer une exception vérifiée doit la gérer, sinon le code ne compilera pas.
Toutes les exceptions vérifiées sont des sous-classes de Exception qui n'étendent pas RuntimeException.
Les exceptions non vérifiées sont des conditions exceptionnelles qu'une application ne peut généralement ni anticiper ni surmonter par elle-même.
Un exemple d'exception non vérifiée est NullPointerException, qui se produit quand une méthode attend une valeur non nulle mais reçoit null.
Ce type d'exception n'est pas vérifié à la compilation : les méthodes qui lancent des exceptions non vérifiées ne sont pas tenues de l'indiquer dans leur signature, et le code qui appelle une méthode susceptible de lancer une exception non vérifiée n'est pas tenu de la gérer.
Toutes les exceptions non vérifiées héritent de RuntimeException, qui est elle-même une extension de Exception.
Une méthode en Java peut lancer une exception à l'aide de l'instruction throw.
Quand on lance une exception vérifiée depuis une méthode, il faut l'indiquer dans la signature de la méthode à l'aide du mot-clé throws, comme le montre l'exemple ci-dessous.
Cela force le code appelant à prévoir qu'une exception peut être lancée et à la gérer en conséquence.
public class InsufficientBalanceException extends Exception {
}
public class BankAccount {
public void withdraw(double amount) throws InsufficientBalanceException {
if (balance < amount) {
throw new InsufficientBalanceException();
}
// rest of the method implementation
}
}
Quand on lance une exception non vérifiée depuis une méthode, il n'est pas nécessaire de l'indiquer dans la signature de la méthode, même si c'est possible.
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
En Java, la gestion des exceptions se fait avec les mots-clés try, catch et finally.
try.try est suivi d'un ou plusieurs blocs catch qui capturent les exceptions lancées dans le bloc try.catch sont éventuellement suivis d'un bloc finally qui s'exécute toujours après le bloc try, qu'une exception ait été lancée ou non.L'exemple suivant montre comment ces mots-clés fonctionnent :
public class ATM {
public void withdraw(BankAccount bankAccount, double amount) {
try {
System.out.println("Withdrawing " + amount);
bankAccount.withdraw(amount);
System.out.println("Withdrawal succeeded");
} catch (InsufficientBalanceException) {
System.out.println("Withdrawal failed: insufficient balance");
} catch (RuntimeException e) {
System.out.println("Withdrawal failed: " + e.getMessage());
} finally {
System.out.println("Current balance: " + bankAccount.getBalance());
}
}
}
Dans cet exemple, quand aucune exception n'est lancée, voici ce qui s'affiche :
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
En revanche, si l'instruction bankAccount.withdraw(amount) lance une InsufficientBalanceException, voici ce qui s'affiche :
Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0
Ou, si une exception non vérifiée est lancée par bankAccount.withdraw(amount), voici ce qui s'affiche :
Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0
Java possède aussi une catégorie distincte appelée erreurs, qui regroupe des problèmes graves externes à une application.
Un exemple d'erreur est OutOfMemoryError, qui se produit quand une application essaie d'utiliser plus de mémoire que ce qui est disponible sur le système.
Comme les exceptions non vérifiées, les erreurs ne sont pas vérifiées à la compilation. La différence est qu'elles représentent des problèmes au niveau du système et sont généralement lancées par la machine virtuelle Java ou par l'environnement plutôt que par l'application. Les applications ne devraient généralement pas essayer de les capturer ni de les gérer.
Toutes les erreurs en Java héritent de la classe Error.
Comme indiqué précédemment, les exceptions sont des événements qui perturbent le déroulement normal des instructions, et servent à gérer des événements exceptionnels. Il est donc déconseillé d'utiliser des exceptions pour le contrôle du flux dans ton application.