Gérer une erreur
Les erreurs
Commençons par voir ce qui se passe lorsqu'une erreur apparait dans un programme et qu'on ne fait rien de spécial pour la gérer. Le listing suivant montre un programme qui va faire une division par zéro.
|
|
On a donc deux variables entières, et on veut les diviser pour ensuite afficher le résultat à la console. Si vous exécutez ce programme ainsi, vous allez avoir un message d'erreur qui va s'afficher à la console étant donné que la ligne de code 8 veut faire une division par 0, ce qui est interdit dans les entiers.
Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionEx.main(Quotient.java:8)
Le programme affiche un message d'erreur, puis s'arrête brutalement. La ligne 10 ne sera donc pas exécutée, le programme est terminé. Si on regarde d'un peu plus près le message d'erreur affiché à la console, on peut repérer le numéro de la ligne de code qui a provoqué l'erreur, de plus, on a le nom de l'erreur qui a été produite, dans notre cas, il s'agit d'une ArithmeticException.
Gérer les erreurs avec if-else
Une première technique qui est utilisée pour gérer les erreurs est simple, et vous la connaissez déjà depuis le chapitre 3, il s'agit d'utiliser l'instruction if-else pour gérer les cas exceptionnels. Dans notre exemple, le seul cas exceptionnel survient lorsque le dénominateur est nul, revoyons donc notre programme.
|
|
if-elseMaintenant, vous pouvez exécuter ce programme, et il se terminera toujours sans erreurs. En effet, si le dénominateur est différent de zéro, la division se passe sans problèmes et le résultat est affiché à l'écran et si le dénominateur est nul, comme dans notre cas, vous verrez un message sympathique s'afficher dans votre console :
Vous ne pouvez pas faire une division par zéro ! Fin du programme
Cette manière de procéder n'est pas applicable à tous les cas d'erreur possible, en effet, pour certains types d'erreurs que l'on recontrera plus tard, il est impossible de faire une vérification avec une instruction if-else, il faut donc un autre mécanisme. De plus, cette manière de procéder est moins lisible, en effet, en lisant le code du listing j11.2, on ne peut pas voir du premier coup d'oeil que l'erreur gérée est due à un problème arithémtique de division par zéro.
L'instruction try-catch
Comment faire pour capturer une exception et la traiter ? On utilise deux choses : pour commencer, il faut mettre dans un bloc try toutes les instructions susceptibles de provoquer une erreur. On rattache ensuite à ce bloc une ou plusieurs clauses catch qui vont chacun gérer un type précis d'exception.
|
|
try-catchOn a donc mis la ligne qui calcule le quotient et la ligne qui affiche le résultat dans un bloc try, ensuite, on ajoute une clause catch pour gérer les erreurs de type arithmétique. Que se passe-t'il si une erreur survient dans le bloc try ? Et bien, le flux de contrôle est directement transféré vers la clause catch correspondant au type d'erreur rencontré, ensuite, est exécuté le code de la clause catch, et enfin, le programme continue après le bloc try-catch.
Chaque cause catch est appelée gestionnaire d'exception et permet donc d'écrire le code qui sera exécuté au cas où une exception est apparue. Regardons un peu la syntaxe de la clause catch : il faut mettre entre parenthèses une variable de type objet, objet représentant l'exception que l'on souhaite attraper.
|
|
catchPour rappel, toutes les exceptions possibles sont représentées, en Java, par une classe. Et donc, en fait, la clause catch reçoit en paramètre un objet qui permet de représenter l'exception qui s'est produite.
Le flux de contrôle
Résumons donc maintenant comment l'instruction try-catch peut altérer le flux de contrôle. Avant tout examinons les différents éléments qui nous intéressent : on a le bloc try et une ou plusieurs clauses catch. On appele le tout l'instruction try-catch.

try-catchCas sans erreurs
Tout d'abord, voyons comment évolue le flux de contrôle dans un cas normal avec aucune erreur se produisant.
- Le code se trouvant avant l'instruction
try-catchest exécuté ; - Le code du bloc
tryest exécuté complètement ; - Le flux de contrôle saute à la fin de l'instruction
try-catchet poursuit son cours normal.
Cas avec une erreur
Voyons maintenant ce qui se passe lorsqu'une certaine erreur survient dans le bloc try.
- Une erreur survient quelque part dans le bloc
try; - Le flux de contrôle quitte immédiatement le le bloc
tryet se rend à la clausecatchcorrespondant à l'erreur qui est apparue. La clausecatchest exécutée complètement ; - Le flux de contrôle saute à la fin de l'instruction
try-catchet poursuit son cours normal.
Remarquez que si vous n'avez pas spécifié de clause catch pour un certain type d'erreur qui apparait, le programme s'arrête avec un message d'erreur comme on l'a vu en début de section.
La clause finally
Enfin, il reste un dernier élément que l'on peut ajouter optionnellement à l'instruction try-catch, il s'agit d'une clause finally. La clause finally représente un bloc de code qui sera exécuté de toute façon, que le bloc try se soit terminé sans erreurs ou avec erreur.
Analysons ensemble comment le flux de contrôle est altéré lorsqu'on se trouve face à une instruction de type try-catch-finally.

try-catch-finallyLa différence que l'on note par rapport à l'instruction try-catch est donc la clause finally qui est à tous les coups exécutée en (3) juste avant que le flux de contrôle ne reprenne son cours normal en (4).
On utilise souvent cette clause avec des programmes qui demandent des ressources particulières au système d'exploitation comme des fichiers, des sockets, ... et qu'il faut absolument libérer, même si une erreur se produit dans le programme. On verra quelques exemples dans le chapitre suivant qui traite des entrées/sorties.
Quelques remarques
Tout d'abord, imaginons qu'une erreur se produise et que la clause catch qui gère l'erreur fasse un System.exit, dans ce cas, la clause finally ne sera pas exécutée, System.exit quittant tout de suite le programme.
Maintenant, imaginons qu'une erreur se produise dans le bloc try, le flux de contrôle quitte donc le bloc try, et part à la recherche d'une clause catch correspondant à l'erreur qui est apparue. Si on n'a pas spécifié un telle clause, le flux de contrôle va d'abord passer dans la clause finally et ensuite le programme se terminera avec un message d'erreur comme on l'a vu en début de section.
Enfin, dernière remarque, si vous spécifiez une clause finally, vous n'êtes plus obligé d'avoir au moins une clause catch, le programme du listing j11.5 est donc tout à fait valable. Pourriez-vous dire ce qu'il va afficher à la console ?
|
|
try-finally










Chapitre 11









