US

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.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
public class Quotient
{
    public static void main (String[] args)
    {
        int numerator = 4;
        int denominator = 0;
 
        int quotient = numerator / denominator;
 
        System.out.printf ("%d / %d = %d\n", numerator, denominator, quotient);
 
        System.out.println ("Fin du programme");
    }
}
listing j11.1 Erreur

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.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
public static void main (String[] args)
{
    int numerator = 4;
    int denominator = 0;
 
    if (denominator != 0)
    {
        int quotient = numerator / denominator;
        System.out.printf ("%d / %d = %d\n", numerator, denominator, quotient);
    }
    else
    {
        System.out.println ("Vous ne pouvez pas faire une division par zéro !");
    }
 
    System.out.println ("Fin du programme");
}
listing j11.2 Gérer les erreurs avec if-else

Maintenant, 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.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
public static void main (String[] args)
{
    int numerator = 4;
    int denominator = 0;
 
    try
    {
        int quotient = numerator / denominator;
        System.out.printf ("%d / %d = %d\n", numerator, denominator, quotient);
    }
    catch (ArithmeticException exception)
    {
        System.out.println ("Vous ne pouvez pas faire une division par zéro !");
    }
 
    System.out.println ("Fin du programme");
}
listing j11.3 Gérer les erreurs avec try-catch

On 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.

1 
2 
3 
4 
catch (ClasseException nomvariable)
{
    // ...
}
listing j11.4 Syntaxe de la clause catch

Pour 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.

Flux de contrôle avec try-catch
fig j11.1 Flux de contrôle avec try-catch

Cas sans erreurs

Tout d'abord, voyons comment évolue le flux de contrôle dans un cas normal avec aucune erreur se produisant.

  1. Le code se trouvant avant l'instruction try-catch est exécuté ;
  2. Le code du bloc try est exécuté complètement ;
  3. Le flux de contrôle saute à la fin de l'instruction try-catch et poursuit son cours normal.

Cas avec une erreur

Voyons maintenant ce qui se passe lorsqu'une certaine erreur survient dans le bloc try.

  1. Une erreur survient quelque part dans le bloc try ;
  2. Le flux de contrôle quitte immédiatement le le bloc try et se rend à la clause catch correspondant à l'erreur qui est apparue. La clause catch est exécutée complètement ;
  3. Le flux de contrôle saute à la fin de l'instruction try-catch et 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.

Flux de contrôle avec try-catch-finally
fig j11.2 Flux de contrôle avec try-catch-finally

La 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 ?

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
try
{
    System.out.println (5 / 0);
}
finally
{
    System.out.println ("Libération des ressources systèmes");
}
 
System.out.println ("Fin du programme");
listing j11.5 Une instruction try-finally
  • Espace membre
  • Learning Center
  • Les forums
  • Livre d'or
  • Imprimer
  • Boutique
  • Info
  • Règlement
  • Erreur
  • Newsletter

MyPagerank.Net

Firefox 3.6

Browse Happy logo

Open Clip Art Library

Join our Facebook Group

Twitter

Copyright © 2000-2013 UKO. Toute reproduction strictement interdite sans autorisation du webmaster

Valid XHTML 1.1 !
Valid CSS2 !
Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0
ICRA Internet Content Rating Association
Creative Commons License
Site optimisé pour Firefox avec une résolution 1024x768 --- Page chargée en 0.0650961 secondes --- This site uses Thumbshots previews