Gestion des exceptions

publicité
Gestion des exceptions
Même lorsqu’un programme est terminé, certaines circonstances exceptionnelles peuvent
compromettre l’exécution de celui-ci. Données incorrectes, fin de fichier prématuré, etc..
Plusieurs langages disposent d’un mécanisme très souple nommé gestion des exceptions
et qui permet de dissocier la détection d’une anomalie de son traitement, ce qui permet
d’avoir une plus grande lisibilité des programmes.
Gestion des erreurs avec des conditions
Avec le gestionnaire d’exception
errorCodeType readFile {
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode==0){
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
}
Une exception est une rupture de séquence déclenchée par une instruction throw
comportant une expression de type classe. Il y a alors un branchement à un ensemble
d’instructions try catch et le choix du bon gestionnaire d’exception est fait en fonction du
type de l’objet mentionné par le throw.
On trouve 2 types d’exception : celle qui peuvent être évitées en améliorant le code et
celles qui ne le peuvent pas. Les premières sont nommées exceptions non vérifiées, par
exemple, lorsqu’on veut diviser par 0, le système génère une ArithmeticException. Dans
ce cas-ci, nous éviterons de diviser par 0 en améliorant le code. Les secondes sont
nommées exceptions vérifiées et elles sont vérifiées par le compilateur avant l’exécution
du programme. Les instructions qui les lancent doivent être insérées dans un bloc try. .
Page 1
Exceptions non vérifiées (unchecked)
Les erreurs provoquées par une exception non vérifiée peuvent être évitées, car elles sont
souvent provoquées par le programme.
Exemple
class TestException{
public static double sqrt(double x){
if(x < 0) throw new IllegalArgumentException();
return Math.sqrt(x);
}
public static void main(String[] args){
try{
System.out.println(sqrt(-25));
}
catch(Exception e){
System.out.println("exception : " + exception);
}
System.out.println("Fin du test");
}
}
Résultat en console
Exception : java.lang.IllegalArgumentException
Fin du test
Par contre, ce genre de programme n’est pas réaliste, car ces erreurs peuvent être
anticipées et donc gérées par un code standard. Ex : ne pas faire sqrt si x = 0;
Exceptions vérifiées (checked)
Les erreurs provoquées par une exception vérifiée ne peuvent généralement être évitées,
car elles sont souvent provoquées par un accès externe. Un try catch doit être ajouté.
Exemple
public static void main(String[] args){
int n = 0;
try{
String input = args[0];
System.out.println("input = " + input);
n = Integer.parseInt(input);
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("Pas d’entree : " + e);
}
catch(NumberFormatException e){
System.out.println("Conversion impossible : " + e);
}
finally{
System.out.println("n = " + n);
}
}
Résultat en console si on ne passe aucun paramètre en ligne de commande
Pas d’entree : java.lang.ArrayIndexOutOfBoundsException
n = 0
Résultat en console si on passe #123 en paramètre
Input = #123
Conversion impossible : java.lang.NumberFormatException
n = 0
Résultat en console si on n’entre 123 en paramètre
Input = 123
n = 123
Page 2
Il peut y avoir plusieurs catch, mais 1 seul sera exécuté selon l’exception lancé par le
throw. Il peut y avoir qu’un seul finally mais il est optionnel. S’il est présent, il est
toujours exécuté. Pour chaque try, il doit avoir au moins 1 catch ou un finally.
Exemple avec les tableaux
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.print("Entrez la taille du tableau :");
int indice = sc.nextInt();
try{
int tab[] = new int[indice];
//1ère exception
for(int i=0; i <= indice; i++){
//2e exception
tab[i] = i + 1;
System.out.println("tab[i] = " + tab[i]);
}
}
catch(NegativeArraySizeException e){
System.out.println("Taille du tableau négative");
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("Indice en dehors du tableau");
}
}
Exemple avec les fichiers
try{
reader = new FileReader(filename);
Scanner in = new Scanner(reader);
readData(in);
reader.close();//May never get here
}catch(Exception exception){
exception.printStackTrace();
}
try{
reader = new FileReader(filename);
Scanner in = new Scanner(reader);
readData(in);
}catch(Exception exception){
exception.printStackTrace();
}finally{
reader.close();//toujours exécutée!
}
Autre exemple avec les fichiers
public static void main()
{
BufferedReader entree;
String line, fichier = JOptionPane.showInputDialog("Fichier :");
try{
entree = new BufferedReader(new FileReader(fichier));
while((line = entree.readLine()) != null){
System.out.println(line);
}
}catch(FileNotFoundException fnf){
System.err.format("File: %s not found%n", fichier);
}catch(IOException e){
System.err.println(e.toString());
}finally{
if(entree != null){
try{
entree.close();
}catch(IOException io){}
}
}
}
Page 3
Java fournit de nombreuses classes prédéfinies dérivées de la classe Exception que voici :
Exemple des principales exceptions
Survient quand une opération arithmétique n’a pas pu être
exécutée.
try {
ArithmeticException
int c = 99 / 0;
} catch (ArithmeticException e) {
System.out.println("div by 0: " + e);
}
Survient quand un index invalide est utilise sur un tableau, un
ArrayIndexOutOfBoundsException Array ou une String
try {
ou
int c[] = {1,2,3};
IndexOutOfBoundsException
c[42] = 99;
ou
} catch (IndexOutOfBoundsException e) {
StringIndexOutOfBoundsException
System.out.println("index invalid : " + e);
}
ArrayStoreException
Survient lorsqu’un mauvais objet tente d’être stocké dans un Array.
NegativeArraySizeException
Survient si un array est créé avec une taille négative.
Survient lorsqu’une application tente de loader une classe qui n’est
pas trouvée.
try{
ClassNotFoundException
Class.forName("com.mysql.jdbc.Driver");
}catch(ClassNotFoundException e){
System.out.println("Driver not found");
}
Survient lorsqu’on tente de convertir une string dans un format
numérique mais que la string initiale n’est pas un nombre.
try{
NumberFormatException
int i = Integer.parseInt("HELLO");
}catch(NumberFormatException e){
e.printStackTrace();
}
Survient lorsqu’on ouvre un fichier qui n’existe pas.
try{
FileNotFoundException
file = new FileInputStream("abc.txt");
}catch(FileNotFoundException e){
System.out.println("File does not exist."+e);
}
Survient lorsque la lecture ou l’écriture ne fonctionne
try{
IOException
while((k = file.read() ) != -1){
System.out.print((char)k);
}
file.close();
}catch(IOException e){
System.out.println("IO problem. " + e);
}
Page 4
La hiérarchie des exceptions
Toutes les exceptions dérivent de la classe Throwable.
La classe Error représente une erreur grave intervenue
dans la machine virtuelle Java ou dans un sous-système
Java. L'application Java s'arrête instantanément dès
l'apparition d'une exception de la classe Error.
La classe Exception représente des erreurs moins
graves. Les exceptions héritant de la classe
RuntimeException n'ont pas besoin d'être détectées
impérativement par des blocs try/catch.
Les exceptions de type Error et RuntimeException sont dites unchecked exceptions car les
méthodes n'ont pas d'obligation à les traiter ou à déclarer leur propagation explicitement.
Il n'est pas recommandé de créer ses propres exceptions en dérivant d'une exception de
type RuntimeException. Même si cela peut sembler plus facile puisqu'il n'est pas
obligatoire de déclarer leur propagation, cela peut engendrer certaines difficultés comme:
 oublier de traiter cette exception
 ne pas savoir que cette exception peut être levée par une méthode.
Cependant, l'utilisation d'exceptions de type unchecked se répend de plus en plus depuis
la diffusion de la plate-forme .Net qui ne propose que ce type d'exceptions.
Créer vos propres exceptions
Il est préférable d'utiliser les exceptions fournies par Java lorsqu'une de ces exceptions
répond au besoin plutôt que de définir sa propre exception. Vous pouvez créer une classe
qui hérite de la classe exception qui sera créé et lancer par vos objets pour être attrapée et
plus précise pour vos propres exceptions.
Pour créer la nouvelle exception il faut :
 Fournir deux constructeurs
 Un constructeur qui accepte une String pour décrire la raison de l’exception
Exemple
public class InsufficientFundsException extends Exception {
public InsufficientFundsException() {}
public InsufficientFundsException(String message)
super(message);
{
}
}
Et elle sera lancée par un objet qui gère les comptes en banque
Exemple
if(amount > balance){
throw new InsufficientFundsException(
"withdrawal of " + amount + " exceeds balance of " + balance);
}
Page 5
Téléchargement