Autres mécanismes (non objet) - Le Mécanisme des exceptions
Définition : Le mécanisme des exceptions est une technique de gestion d'erreurs qui permet de transmettre une erreur en dehors du flot normal de la pile d'appel.
La gestion d'erreurs
La gestion d'erreurs se charge des défauts de programme (cas anormaux) se produisant au cours de l'exécution. Son objectif n'est pas simplement d'afficher un message pour informer d'un problème. Elle doit permettre aux parties du programme contenues dans la pile d'appel d'effectuer un traitement. Pour une gestion d'erreurs, il est nécessaire d'avoir
- Une détection d'erreur, si condition alors il y a erreur de catégorie X. Cette portion de code détecte une condition d'erreur mais ne la traite pas. Son objectif est de signaler l'erreur au reste du code de l'application. Elle est signalée à travers une donnée particulière correspondant à la catégorie de l'erreur.
- Un gestionnaire d'erreur, si erreur de catégorie X alors voici le traitement à faire. Un gestionnaire d'erreur définit un code de traitement pour une catégorie particulier d'erreur. Pour traiter cette erreur, les gestionnaire doit recevoir la donnée définie dans le code de détection. Une partie de programme peut définir plusieurs gestionnaires pour des catégories différentes d'erreur. Pour une catégorie d'erreur, plusieurs gestionnaires peuvent être définis dans la pile d'appel.
- Un mécanisme de transmission de l'erreur, si indication d'erreur X alors transmettre l'exécution au gestionnaire d'erreur X. Le cours normal de l'exécution doit s'arrêter et continuer avec le code d'un gestionnaire de cette erreur. Ce gestionnaire est trouvé en remontant la pile d'appel.
Le mécanisme de transmission de l'erreur
Un moyen d'effectuer cette transmission entre la détection et le gestionnaire est d'utiliser la valeur de retour des fonctions. Mais cette transmission n'est pas automatique, elle doit être écrite par le programmeur pour chaque appel d'une fonction afin de remonter la pile d'appel. Pour avoir une transmission automatique, le mécanisme de gestion d'erreur doit enregistrer pour chaque gestionnaire d'erreur se trouvant dans la pile d'appel : la catégorie d'erreur et l'adresse de début du code à exécuter. Dés qu'une erreur est signalée, la transmission se fait par un saut ("goto") à l'adresse du début du bloc du dernier gestionnaire enregistré pour cette catégorie d'erreur.
Le mécanisme d'exception du langage Java
Il est basé sur :
- Une exception est un objet encapsulant des informations sur l'erreur. Chaque catégorie d'erreur est représentée par une classe (donc un type)
- La levée d'une exception provoque la rupture de séquence et transmet l'instance d'une classe d'exception. Le choix du gestionnaire se fait en fonction du type de la classe d'exception.
- La capture d'une exception déclare le gestionnaire : le type de la classe d'exception pris en compte et le bloc de traitement. Ce bloc récupère l'instance tranmise par la levée.
Les classes d'exception
Une classe est considérée comme une classe d'exception si elle possède un lien
"est-un" avec la classe java.lang.Throwable
. Cette classe définit un
comportement par défaut :
- son constructeur prend en paramètre une chaîne de caractères utilisée comme message d'erreur;
getMessage()
: message d'erreur fourni lors de l'instanciationprintStackTrace()
: affichage des informations sur la pile d'appel.
L'API Java fournit déjà une hiérarchie de classes d'exception. Chacune de ces classes correspond à une catégorie d'erreur
java.lang.Throwable
Java.lang.Error
java.lang.AssertionError
java.lang.VirtualMachineError
Java.lang.Exception
java.lang.ClassNotFoundException
java.io.IOException
java.io.FileNotFoundException
java.lang.RuntimeException
java.lang.NullPointerException
java.lang.ArrayIndexOfBoundsException
La levée d'une exception
Le bloc de détection lève une exception grâce à l'instruction throw
suivie de
l'instance d'une classe d'exception
if(conditionErreur)
throw new LaClasseException("Message_d'erreur");
L'instruction throw
provoque la rupture de séquence, le saut vers un
gestionnaire de cette erreur.
La capture d'une exception
La capture s'effectue à l'aide d'un bloc try/catch/finally
try{
// ...
}
catch(Nom1Exception e){
// ...
}
catch(Nom2Exception e){
//...
}
catch(Nom3Exception | Nom4Exception e){
//...
}
[finally{}]
try délimite les instructions où s'appliquent la ou les captures suivantes.
catch déclare le gestionnaire d'une exception. Chaque clause catch
contient un seul paramètre correspondant au type de l'exception à capture. À
l'exécution, ce paramètre va référencer l'instance précisée dans l'instruction
throw
. Toutes les clauses catch
d'un bloc try/catch/finally
doivent avoir
des types différents de paramètre.
finally Cette clause est optionnelle. Si elle est présente, son bloc
d'instructions est systématiquement exécuté après la fin du bloc try ou du bloc
d'une clause catch
.
Il y a toujours une seule clause try
et au moins une clause catch
. Si aucune
exception n'est levée dans les instructions des clauses try
ou catch
,
l'exécution continue normalement après le bloc try/catch/finally
. Par défaut,
la machine virtuelle capture toutes les exceptions et affiche un message
d'erreur.
Spécification de la propagation
Une exception est dite propagée par un bloc de code si cette exception n'est pas
capturée dans ce bloc. Cette propagation se fait en "remontant" la pile d'appel.
En Java, la clause throws
permet de spécifier cette propagation dans la
déclaration d'une méthode ou d'un constructeur. Cette spécification est
obligatoire :
- pour les sous-types de la classe
java.lang.Exception
- mais non sous-types de la classe
java.lang.RuntimeException
.
Ces exceptions sont dites contrôlées/vérifiées. Elle correspondent à la majorité des exceptions définies par l'API Java.
Pour une exception contrôlée/vérifiée, le compilateur Java provoque une erreur
si le corps d'une méthode ou d'une constructeur propage (ne capture pas) cette
exception sans déclaration dans la clause throws
.