MIM1
TD 4 de POOGL
Exception
Vincent BOUDET
Bureau 343 (84-70)
email vboudet@ens-lyon.fr
23 Janvier 2000
Ce TD est volontairement plus cours, afin de parler des projets en fin
de séance.
A Pourquoi gérer les erreurs ?
En informatique, la gestion des erreurs est une préocuupation majeure.
On doit dsouvent gérer des erreurs telles que la division par 0, l'accès à
une zone mémoire interdite, etc. On doit se soucier des erreurs provoquées par
le non-respect des procédures normales d'utilisation. On doit également
prendre en compte l'apparition d'événements inopinés, comme un disque plein,
une disquette non présente, une erreur de frappe, etc.
De plus, la gestion fine des erreurs facilite grandement la mise au point d'un
programme.
Dans les langages structurés classiques, il est habituel d'utiliser
les valeurs retournées par les fonctions comme code d'erreur. La fonction
appelante se charge alors de traiter les différents cas d'erreur. Le code est
alors particulièrement peu lisible, car le deroulement du programme n'est pas
saré du traitement des erreurs.
B Fonctionnement des exceptions
Java, comme beaucoup de langages récents, utilise les exceptions
pour gérer les erreurs ou les situations inhabituelles.Les exceptions
sont des objets créés lors de situations d'erreurs et qui sont traités
dans des sections réservés à cet effet.
Concrètement, quand le programme détecte une situation anormale ou une erreur
il lève throw une exception. La levée d'une exception est nécessairement
inscrite dans un bloc d'essai (try), elle provoque instantanément la sortie du bloc concerné et doit être capturé dans un bloc catch
C Exemple
import java.io.*;
public class LireDouble
{
public static void main(String[] argv)
{
String ch;
double x;
BufferedReader fluxEntree;
fluxEntree = new BufferedReader(new InputStreamReader(System.in));
try
{
ch = fluxEntree.readLine();
x = Double.valueOf(ch).doubleValue();
System.out.println(``Double lu : `` +x);
}
catch (Exception e)
{
System.out.println(``Erreur de lecture d'un double:'' + e);
System.exit(1);
}
}
}
D Lever une exception
Dans le pragrahe précédent, l'exception avait été levée par une méthode d'une
classe de la bibliothèque Java, donc de façon invisible pour le
programmeur. Pour lever soi même une exception on utilise l'instruction
throw.
throw newIllegalAccesError(``Acces interdit à la méthode Toto.bidule()'');
E Créer une classe d'exception
On peut créer des sous-classes de Exception ou d'une de ses sous-classes.
Par exemple :
import java.io.*;
public class LectureErreur extends Exception
{
LectureErreur()
{}
LectureErreur(String message)
{
super(message);
}
}
On peut alors l'utiliser de la manière suivante :
import java.io.*;
public class ES
{
public static void main(String[] argv) throws LectureErreur
{
String ch='''';
BufferedReader fluxEntree;
fluxEntree = new BufferedReader(new InputStreamReader(System.in));
try
{
ch = fluxEntree.readLine();
x = Double.valueOf(ch).doubleValue();
System.out.println("Double lu : " +x);
}
catch (Exception e)
{
throw new LectureErreur(``Erreur de lecture d'un réel double'');
}
}
}
La méthode appelante va pouvoir traiter cette erreur en prenant en compte
le contexte dans lequel elle est survenue.
Pour qu'une méthode puisse déléguer le traitement d'une exception
à une méthode appelante, elle doit le signaler par une clause throws
dans son en-tête. Pour qu'une exception soit controlée, il faut qu'elle soit
déclarée par throws ou capturée par catch.
F Ajout de champ
L'utilisateur a parfois besoin de renseignements complémentaires. On aimerait
par exemple savoir quelle chaine de caractères a été lue.
import java.io.*;
public class LectureErreur extends Exception
{
String chaineLue = null;
LectureErreur()
{}
LectureErreur(String message)
{
super(message);
}
LectureErreur(String message, String chaine)
{
super(message);
this.chaineLue=chaine;
}
String toString()
{
String ch;
if (chaineLue != null )
{
ch = getMessage() + ``\n Chaine lue ayant provoquée l'erreur : ``;
ch = ch + chaineLue;
}
else
ch = getMeassge();
return ch;
}
}
G Finally
L'instruction try ... catch peut comporter une clause finally
qui sera executée dans tous les cas. Cette clause est peu utilisée, elle
sert généralement à fermer les flux ouverts dans des opérations
d'entrées-sorties.
H À vous
H.1 Tampon de nombres entiers
Créer une classe TamponEntiers qui contient un champ de type int[]. Il a une
capacité initiale communiquée en argument du constructeur. Quand le tableau
est saturé (pensez aux exceptions), la méthode agrandir() construit un nouveau
tableau de capacité supérieure. Cette classe devra comporter
les méthodes suivantes :
-
ajouter(int element)
- vider()
- imprimer()
- int element(int indice)
- int nbElements()
H.2 SaturationMemoireException
Créer une classe SaturationMemoireException étendant la classe
Exception. On la dotera d'un constructeur vide et d'un
constructeur prenant une chaine comme argument afin de donner
des précisions sur la nature des circonstances ayant provoqué la
levé de l'exception.
Les tampons TamponEntiers peuvent provoquer un arrêt brutal
du programme lors de l'
appel à la méthode agrandir() quand la quantité de mémoire
disponible est insuffisante. Capturer l'erreur de type
OutOfMemoryError qui peut survenir dans la méthode agrandir()
et lever alors une exception de type SaturationMemoireException.
Elle sera propagée jusqu'à la méthode ajouter() afin que
l'utilisateur ait la possibilité d'imprimer le travail en cours.
Tester cette nouvelle classe TamponEntier en ajoutant des nombres entiers
jusqu'à provoquer la saturation de la mémoire.
H.3 La factorielle
Écrire un programme simple qui calcule la factorielle d'un nombre donné
sur la ligne de commande.
À partir de ce programme simple, modifiez le en utilisant des classes
d'exception pour rattraper les erreurs suivantes :
-
pas le paramètre attendu sur la ligne de commande,
- paramètre non entier ,
- paramètre entier négatif,
- mettre l'entier 20.
Dans les deux premiers cas, une exception est signalée.
Dans les deux derniers cas, le résultat est faux.
Vous devez modifier le programme pour que, dans chacun de ces cas,
l'erreur soit précisée à l'utilisateur.
Dans le premier cas, on souhaite que le programme affiche par exemple :
Indiquez le nombre d'entiers sur la ligne de commande
et si le paramètre indiqué est -4 :
-4 est négatif : la factorielle n'est pas définie.
This document was translated from LATEX by
HEVEA.