Début de la boite de navigation du chapitre
Exceptions
Icône de la faculté
Chapitre no 9
Leçon : Java
Chap. préc. :Héritage et polymorphisme
Chap. suiv. :Gestion de fichiers
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Java : Exceptions
Java/Exceptions
 », n'a pu être restituée correctement ci-dessus.

Introduction

modifier

Pour avoir un programme robuste, il faut gérer les erreurs qui peuvent subvenir lors de l'exécution du programme.

Une erreur ou une exception se produit lorsque les conditions d'exécution sont telles que la poursuite du programme devient impossible ou incorrecte. Par exemple il peut s'agir d'un débordement de tableau, d'un manque de mémoire, d'une division par zéro ou même, comme nous allons le voir par la suite, d'une exception levée par le programmeur.

Cela oblige à écrire de nombreux tests qui n'ont pas de rapport direct avec la tâche principale du programme.

Ce n’est pas toujours facile avec les langages classiques, tel le C où le seul moyen de gérer les exceptions est de retourner des constantes comme 0 ou -1 par une méthode pour signifier que son exécution s'est respectivement déroulée sans ou avec problème...

Java propose une approche très différente :

class Point {
  public static final int X_MAX = 1024, Y_MAX = 768;
  private int x, y;

  public Point (int a, int b) throws Exception {
    if (a < 0 || a >= X_MAX || b < 0 || b >= Y_MAX) {
      throw new Exception("Coordonnées illégales.");
    }
    x = a;
    y = b;
  }
}

Qu'est-ce qu'une exception

modifier

C'est un objet de la classe java.lang.Throwable, classe mère de toutes les erreurs et exceptions. Cette classe a pour sous-classes :

  • java.lang.Error dont doivent hériter les erreurs graves qui causent l'arrêt du programme comme par exemple la classe OutOfMemoryError,
  • java.lang.Exception dont doivent hériter les erreurs qui doivent impérativement être traitées ou capturées comme par exemple la classe FileNotFoundException,
  • java.lang.RuntimeException, qui hérite de java.lang.Exception, et dont doivent hériter les erreurs qui peuvent ne pas être traitées ou capturées, comme par exemple les classes NullPointerException, NumberFormatException ou encore ArrayIndexOutOfBoundsException.

Capturer une exception

modifier

Lorsqu'une exception est lancée, elle se propage d'une méthode à la méthode appelante jusqu'à être capturée. Si elle ne l'est pas, le programme s'arrête et le contenu de la pile des méthodes traversées est indiqué à l'utilisateur.

Syntaxe d'une interception :

try {
  bloc_1
} catch(type_exception_1 arg_1) {
  bloc_2
} catch(type_exception_2 arg_2) {
  bloc_3
}...
} finally {
  bloc_N
}

Si une erreur survient dans le bloc d'instructions no 1, l'interpréteur le quitte immédiatement et une exception est levée. Comme nous nous trouvons dans un bloc try/catch elle sera peut être attrapée par le catch correspondant, auquel cas son bloc d'instructions sera exécuté. Si aucun des catch présents ne l'attrapent, l'erreur se propage à la méthode appelante et ainsi de suite. Dans tous les cas le bloc finally (facultatif) est exécuté, même en présence d'un return dans le bloc no 1 exécuté sans erreur.

Depuis la version 7 de Java, il est possible d'utiliser le catch de multiple Exceptions :

try {
  ...
} catch(IOException|SQLException ex) {
  .....
}

Un exemple continuant celui de l'introduction :

try {
  Point p = new Point(u, v);
} catch(Exception e) {
  System.out.println("Problème avec les coordonnées du point :");
  System.out.println(e.getMessage());
  e.printStackTrace();
}

À noter que de nombreuses méthodes de la bibliothèque Java (l'API Java) peuvent générer des exceptions. C’est le cas par exemple de la méthode de classe int Integer.parseInt(String) qui a pour fonction de convertir une chaîne de caractères en un entier (par exemple "123" en l'entier 123). Si la chaîne ne contient pas un nombre, la méthode lève une NumberFormatException. Comme cette exception n'a pas obligation à être interceptée (cf. #Qu'est-ce qu'une exception), il n’est pas impératif, quoique conseillé, de placer chaque appel à int Integer.parseInt(String) au sein d'un bloc try/catch.

Méthodes de l’objet Exception

modifier
  • printStackTrace() : affiche l'état de la pile lors de la remontée de l'exception. Utile pour trouver les causes de celle-ci.

Lancer une exception

modifier

Une exception peut être lancée via la syntaxe suivante :

throw exception;

exception est une expression dont la valeur doit être un objet de type Throwable.

Si une méthode est susceptible de lancer une exception de type T ou U, elle doit :

  • soit l'attraper via un bloc try/catch adéquat,
  • soit déclarer qu'elle est susceptible de laisser échapper des exceptions via l’expression throws T, U placée en fin d'en-tête de méthode (cf. l'en-tête du constructeur de la classe Point ici et ).

Créer son propre type d'exception

modifier

On le peut en héritant de la class Exception :

class CoordonneesIllegalesException extends Exception {
  public CoordonneesIllegalesException () {
    super("Coordonnées illégales.");
  }

  public CoordonneesIllegalesException (String msg) {
    super(msg);
  }

  public CoordonneesIllegalesException (Throwable cause) {
    super(cause);
  }

  public CoordonneesIllegalesException (String msg, Throwable cause) {
    super(msg, cause);
  }
}

Le constructeur de la classe Point de l’exemple introductif peut alors s'écrire :

  public Point (int a, int b) throws CoordonneesIllegalesException {
    if (a < 0 || a >= X_MAX || b < 0 || b >= Y_MAX) {
      throw new CoordonneesIllegalesException();
    }
    x = a;
    y = b;
  }

Exceptions courantes

modifier
  Pour aller plus loin, voir : b:Programmation Java/Débogage.