Le langage de programmation Java utilise des exceptions pour gérer les erreurs et les 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 : l'action de lever une exception s'appelle lancer une exception, et l'action de traiter une exception s'appelle intercepter 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 lorsqu'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 traiter, 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 traiter.
Un exemple d'exception non vérifiée est NullPointerException, qui se produit lorsqu'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 obligées 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 obligé de la traiter.
Toutes les exceptions non vérifiées héritent de RuntimeException, qui est elle-même une extension d'Exception.
Une méthode en Java peut lancer une exception à l'aide de l'instruction throw.
Lorsqu'une méthode lance une exception vérifiée, elle doit l'indiquer dans sa signature à l'aide du mot-clé throws, comme le montre l'exemple ci-dessous.
Le code appelant est ainsi obligé d'anticiper qu'une exception peut être lancée et de la traiter 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
}
}
Lorsqu'une méthode lance une exception non vérifiée, elle n'est pas obligée de l'indiquer dans sa signature, 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, le traitement des exceptions se fait à l'aide des mots-clés try, catch et finally.
try.try est suivi d'un ou plusieurs blocs catch qui interceptent 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, lorsqu'aucune exception n'est lancée, la sortie suivante s'affiche :
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
En revanche, si l'instruction bankAccount.withdraw(amount) lance une InsufficientBalanceException, la sortie suivante 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), la sortie suivante 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 Errors : ce sont des problèmes graves externes à l'application.
Un exemple d'erreur est OutOfMemoryError, qui se produit lorsqu'une application essaie d'utiliser plus de mémoire que le système n'en dispose.
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 intercepter ni de les traiter.
En Java, toutes les erreurs héritent de la classe Error.
Dans cet exercice, tu vas mettre en place la gestion des erreurs d'une calculatrice d'entiers simple. Pour simplifier les choses, des méthodes permettant de calculer l'addition, la multiplication et la division sont fournies.
L'objectif est d'obtenir une calculatrice fonctionnelle qui renvoie une String selon le format suivant : 16 + 51 = 67, lorsqu'on lui fournit les arguments 16, 51 et +.
CalculatorConundrum calculator = new CalculatorConundrum();
calculator.calculate(16, 51, "+");
// => returns "16 + 51 = 67"
calculator.calculate(32, 6, "*");
// => returns "32 * 6 = 192"
calculator.calculate(512, 4, "/");
// => returns "512 / 4 = 128"
La méthode principale à implémenter dans cette tâche sera la méthode CalculatorConundrum.calculate().
Elle prend trois arguments.
Les deux premiers arguments operand1 et operand2 sont les nombres entiers sur lesquels porte l'opération.
Le troisième argument operation est de type String et, pour cet exercice, il est nécessaire d'implémenter les opérations suivantes :
String +
String *
String /
Modifie la méthode CalculatorConundrum.calculate() pour gérer les opérations invalides :
operation vaut null, une IllegalArgumentException doit être levée avec le message Operation cannot be null.operation vaut "", une IllegalArgumentException doit être levée avec le message Operation cannot be empty.operation est une opération autre que +, * ou /, une IllegalOperationException doit être levée avec le message Operation '{operation}' does not exist.calculator.calculate(10, 1, null);
// => throws IllegalArgumentException with message "Operation cannot be null"
calculator.calculate(10, 1, "");
// => throws IllegalArgumentException with message "Operation cannot be empty"
calculator.calculate(10, 1, "-");
// => throws IllegalOperationException with message "Operation '-' does not exist"
En Java, une tentative de division par zéro lève une ArithmeticException.
Modifie la méthode CalculatorConundrum.calculate() pour intercepter cette exception, puis lever une IllegalOperationException avec le message Division by zero is not allowed et l'ArithmeticException interceptée comme cause.
calculator.calculate(512, 0, "/");
// => throws IllegalOperationException with message "Division by zero is not allowed"
Inscris-toi sur Exercism pour apprendre et maîtriser Java avec 26 concepts158 exercices, et un vrai mentorat humain, le tout gratuitement.