Les exceptions


Lecture : chapitre 10 du livre "Programmer en Java".

Description

Le compilateur (ou un environnement de développement comme Eclipse) pemet de détecter, avant l'exécution, un certain nombre d'erreurs : erreur de syntaxe, affectation à une variable d'un objet de type incompatible, etc. Si ces erreurs en sont pas réglées, l'exécution du programme se sera pas permise.
D'autres erreurs peuvent se produire lors de l'exécution :

Même lorsqu'un programme est bien conçu, certains « plantages » peuvent se produire : erreur de lecture/écriture dans fichier (e.g. parce qu'un disque dur est défectueux, ou parce que le fichier est effacé pendant qu'on lit/écrit dedans), connexion réseau interrompue, construction d'une date par analyse d'une chaîne de caractère qui est au mauvais format, etc. Les exceptions sont un mécanisme pour gérer ce type de cas.
Vous avez déjà probablement été confrontés à des exceptions lors de l'exécution de vos programmes : ArrayOutOfBoundException lorsque vous tentez d'accéder à un élément d'un tableau vide ou à un index négatif, ou supérieur à la taille d'un tableau, NullPointerException lorsque vous invoquez une méthode sur un référence nulle, etc. Ces exceptions provoquent, lorsque vous ne les « interceptez » pas, l'arrêt du programme et l'affichage d'une trace d'erreur dans la console. Java vous » passe « les exceptions déclenchées (cf. ci-dessous) sous forme d'instances de classes qui dérivent de la classe Exception ou de sa classe-mère Throwable (cf. l'API).

Nous allons voir ici comment « gérer » ce type d'exceptions (en les « interceptant »). Vous en aurez notamment besoin si vous réalisez la partie "écriture des résultats dans un fichier" du projet sur l'extraction des triplets syntaxiques". Il est également possible de déclencher vous-même volontairement des exceptions et de créer des classes qui dérivent de Exception. Nous n'en aurons pas besoin pour la réalisation du projet et n'aborderons pas ces questions (je vous renvoie au livre de C. Delannoy et à celui de B. Eckel pour plus de détails).

Intercepter une exception

Dans la documentation de l'API, chaque méthode indique, lorsqu'il y a lieu, le type d'exception qu'elle peut générer (» lancer »). Par exemple, si vous regardez la documentation de la classe ArrayList, et de sa méthode get(int) (dans la section Method Detail) vous pouvez lire :
Throws:
IndexOutOfBoundsException - if the index is out of range (index < 0 || index >= size())

Cela signifie que, lorsque vous invoquez la méthode get() sur une instance d'ArrayList, vous risquez de déclencher une exception.

Lorsqu'on sait qu'une instruction (ou plusieurs) peut déclencher une exception, on peut, en Java, spécifier les actions à mener le cas échéant. Il s'agit d'écrire un bloc try-catch. À l'intérieur du bloc (délimité par des accolades) try, on écrit l'instruction (ou les instructions) à risque puis, dans le bloc catch, les instructions à exécuter si l'erreur potentielle se produit. On peut :


Exemple :
      ArrayList<Integer> listeEntiers = new ArrayList<Integer>();

      try
      {
          System.out.println(listeEntiers.get(3));
      }
      catch (IndexOutOfBoundException e)
      {
          System.out.println("Accès en dehors du tableau. Fin du programme.");
          System.exit (-1);
      }

      System.out.println ("On continue le programme");
    

Ici, si l'exécution de la méhode get() provoque une exception, on décide d'afficher un message d'erreur et de terminer l'exécution (System.exit (-1)). Sinon, on passe à l'instruction qui suit le bloc try-catch. En supprimant l'instruction System.exit (-1), en cas d'erreur, on afficherait simplement le message d'erreur et on passerait à la suite.

Dans certaines situations, vous n'êtes pas obligés d'intercepter les exceptions. Pour d'autres, Java vous l'impose. Ce sera le cas lors du travail avec les fichiers.

L'objet e référencé dans le "catch" (vous pouvez le nommer autrement) est une instance de la classe Exception sur lequel vous pouvez invoquer, par exemple, la méthode printStackTrace() (cf. doc de l'API), qui produira à l'écran un affichage énumérant la liste des méthodes invoquées jusqu'à ce que l'erreur se produise.

      ArrayList<Integer> listeEntiers = new ArrayList<Integer>();

      try
      {
          System.out.println(listeEntiers.get(3));
      }
      catch (IndexOutOfBoundException erreur)
      {
          System.out.println("Accès en dehors du tableau.");
          System.out.println("Trace d'exécution :");
          erreur.printStackTrace ();
          System.out.println("On continue le programme...");
      }

      System.out.println ("Suite du programme");
    

Lorsqu'une ou plusieurs instructions peuvent déclencher des exceptions de types différents, on peut exécuter des traitements différenciés. Par exemple, la méthode (statique) parseInt de la classe Integer retourne une objet Integer correspondant à une chaîne de caractères. Integer.parseInt ("123") renverra un entier égal à 123. La méthode déclenche en revanche une exception si la chaîne de caractères ne correspond pas à la représentation textuelle d'un entier. Ci-dessous, le bloc try génère potentiellement deux types d'exceptions différents. Deux catch sont proposés pour gérer chacun d'entre eux.

      ArrayList<Integer> listeEntiers = new ArrayList<Integer>();
      listeEntiers.add (new Integer (1));
      listeEntiers.add (new Integer (-27));
      
      try
      {      
          System.out.println(Integer.parseInt ("123ZY"));
          System.out.println(listeEntiers.get(3));
      }
      catch (IndexOutOfBoundException erreurIndex)
      {
          System.out.println("Accès en dehors du tableau.");
          erreurIndex.printStackTrace();
      }
      catch (NumberFormatException erreurFormatNb)
      {
          System.out.println("Mauvais format d'entier");
          erreurFormatNb.printStackTrace ();
      }

      System.out.println ("Suite du programme");
    

Ici, le fait d'avoir deux blocs catch (notez que dans ce cas, on nomme différemment l'objet correspondant à l'exception interceptée, ici : erreurIndex et erreurFormatNb) permet d'effectuer un traitement différent en fonction du type d'excetion déclenchée.
Il est également possible de proposer un traitement identique pour toutes les exceptions potentielles en interceptant une instance de la classe-mère Exception :

      ArrayList<Integer> listeEntiers = new ArrayList<Integer>();
      listeEntiers.add (new Integer (1));
      listeEntiers.add (new Integer (-27));
      
      try
      {      
          System.out.println(Integer.parseInt ("123ZY"));
          System.out.println(listeEntiers.get(3));
      }
      catch (Exception e)
      {
          System.out.println("Une erreur s'est produite.");
          e.printStackTrace();
      }

      System.out.println ("Suite du programme");
    


Retour page séance 8 ]

Mention légale ]