Vous êtes sur la page 1sur 10

Institut Supérieur des Science Appliquées Année universitaire : 2019-2020

Et de Technologie de Sousse

Matière : Programmation Orientée Objet 2 (Java) Enseignant : Dr. Majd BELLAAJ

Filière : Deuxième Année Cycle Préparatoire

TD 7 : Exceptions
Dans ce TD, on verra en particulier :

 Exemples d’exceptions de type RunTimeException


 Hiérarchie des exceptions
 Définir sa propre exception
 Lancer une exception
 Autres propagations d'exceptions

Une exception est un événement exceptionnel risquant de compromettre le bon


déroulement du programme. Un débordement de tableau, la lecture d’une donnée erronée ou
autre constituent des exemples d’exceptions. Lors de la détection d’une anomalie, une fonction
(en C par exemple) peut essayer de la traiter directement ; elle peut aussi fournir des
informations de retour (par l’intermédiaire d’une variable) indiquant le type de l’anomalie et
laissant au programme appelant le soin de décider de la suite à donner à cette anomalie.
En Java, la fonction peut lancer une exception en indiquant un type d’exception.
L’exception se "propage" de retour de méthode en retour de méthode jusqu’à ce qu’une
méthode la traite. Si aucune méthode ne la prend en compte, il y a un message d’erreur
d’exécution. Suite à une exception, toutes les instructions sont ignorées, sauf les instructions
chargées de capter cette exception.
LES EXCEPTIONS DE TYPE RunTimeException
Exemple1 : les débordements de tableaux (dans main)
L’exécution du programme suivant provoque un message d’erreur indiquant une
exception du type ArrayIndexOutOfBoundsException, et l’arrêt du programme. Le tableau de
4 entiers tabEnt a des indices de 0 à 3. L’accès à la valeur d’indice 5 provoque une exception
non captée.

1
// TestException1.java
public class TestException1 {
public static void main (String[] args) {
int tabEnt[] = { 1, 2, 3, 4 };
// Exception de type java.lang.ArrayIndexOutOfBoundsException non contrôlée par le
//programme ; erreur d’exécution
tabEnt [4] = 0; // erreur et arrêt
System.out.println ("Fin du main"); // le message n’apparait pas
} // main
} // class TestException1

Résultats d’exécution :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at Exeption_.TestException1.main(TestException1.java:18)
Dans le programme suivant, la même erreur d’accès à un élément est captée par le
programme. Lors de la rencontre de l’erreur, les instructions en cours sont abandonnées et un
bloc de traitement (catch) de l’exception est recherché et exécuté. Le traitement se poursuit
après ce bloc sauf indication contraire du catch (return ou arrêt par exemple). Le message "Fin
du main" est écrit après interception de l’exception.
public class TestException2 {
public static void main (String[] args) {
try {
int tabEnt[] = { 1, 2, 3, 4 };
// Exception de type ArrayIndexOutOfBoundsException contrôlée par le programme

tabEnt [4] = 0; // Exception et suite au catch


System.out.println ("Fin du try"); // non exécutée
} catch (Exception e) {
System.out.println ("Exception : " + e); // écrit le message
}
System.out.println ("Fin du main"); // exécutée
}
} // class TestException2
Exemples de résultats d’exécution :
Exception : java.lang.ArrayIndexOutOfBoundsException: 4
Fin du main
Exemple2 : les débordements de tableaux (dans une méthode)
Ci-dessous, l’instruction tabEnt[4] provoque une exception dans la méthode init-
Tableau(). L’instruction qui suit n’est pas prise en compte ; l’exception n’est pas traitée dans
initTableau(). Les instructions qui suivent l’appel de initTableau() dans main() (le programme

2
appelant) sont ignorées également. Par contre, il existe un bloc catch qui traite l’exception. Le
message "Fin de main" est lui pris en compte après le traitement de l’exception.
// PPTestException3.java Exception lancée dans initTableau,
// captee dans main()
class TestException3 {
int[] tabEnt = new int[4];
void initTableau () {
tabEnt[0] = 1; tabEnt[1] = 2;
tabEnt[2] = 3; tabEnt[3] = 4;
tabEnt[4] = 5; // l’exception se produit ici; non captée
System.out.println("Fin de initTableau"); // non exécutée
}
void ecrireTableau () {
for (int i=0; i < tabEnt.length; i++) {
System.out.print (" " + i);
}
System.out.println();
}
} // class TestException3

public class PPTestException3 {


public static void main (String[] args) {
try {
TestException3 te = new TestException3();
te.initTableau(); // l’exception se produit dans initTableau

te.ecrireTableau(); // non exécutée


} catch (Exception e) { // exception captée ici
System.out.println ("Exception : " + e); // exécutée
}
System.out.println ("Fin de main"); // exécutée
} // main
} // class PPTestException3
Résultats d’exécution :
Exception : java.lang.ArrayIndexOutOfBoundsException: 4
Fin de main
L’exception peut aussi être traitée dans initTableau() comme indiqué ci-dessous. Le
programme se poursuit normalement une fois le bloc catch exécuté (retour de initTableau(),
appel de ecrireTableau() et message de fin).
// PPTestException4.java Exception lancée par initTableau()
// captée par initTableau()

3
class TestException4 {
int[] tabEnt = new int[4];
void initTableau () {
try {
tabEnt[0] = 1; tabEnt[1] = 2;
tabEnt[2] = 3; tabEnt[3] = 4;
tabEnt[4] = 5; // l’exception se produit ici
} catch (Exception e) { // captée ici
System.out.println ("Exception : " + e); // écrit le message
}
System.out.println("Fin de initTableau"); // exécutée
}
void ecrireTableau () {
for (int i=0; i < tabEnt.length; i++) {
System.out.print (" " + tabEnt[i]);
}
System.out.println();
}
} // class TestException4

public class PPTestException4 {


public static void main (String[] args) {
TestException4 te = new TestException4();
te.initTableau(); // exception a été captée
te.ecrireTableau(); // exécutée
System.out.println ("Fin de main"); // exécutée
} // main
} // class PPTestException4

Exemples de résultats d’exécution :


Exception : java.lang.ArrayIndexOutOfBoundsException: 4
Fin de initTableau
1234
Fin de main
Autres exemples d’exceptions de type RunTimeException
Les deux instructions suivantes provoquent une exception de type NullPointerException
.s1 est une référence null sur un (futur) objet de type String. On ne peut pas accéder au troisième
caractère de l’objet String référencé par null, d’où l’exception.
String s1 = null; System.out.println (s1.charAt (3));

4
Le programme suivant donne des exemples où une exception est lancée : chaîne à
convertir en entier ne contenant pas un entier (lecture erronée d’un entier par exemple), division
par zéro, transtypage non cohérent de deux objets de classes différentes, etc.
TestException5.java différentes exceptions
import java.awt.*;
public class TestException5 {
public static void main (String[] args) {
String s1 = null;
//exception NullPointerException ci-dessous
//System.out.println (s1.charAt(3));
// convertit la chaine "231" en un entier binaire
int n1 = Integer.parseInt ("231");
System.out.println ("n1 : " + n1);
// exception car la chaine "231x" n’est pas un entier :
// exception NumberFormatException ci-dessous
//int n2 = Integer.parseInt ("231x");
//System.out.println ("n2 : " + n2);
//int d = 0;
//int quotient = 17 / d; // exception de type ArithmeticException
//System.out.println ("quotient : " + quotient);
//Object p = new Point(); // voir chapitre héritage
//Color coul = (Color) p; // exception ClassCastException :
// p n’est pas de la classe Color
System.out.println ("Fin de main");
} // main
} // class TestException5

LA HIÉRARCHIE DES EXCEPTIONS


 Les exceptions constituent un arbre hiérarchique utilisant la notion d’héritage.
Object : la classe racine de toutes les classes
Throwable : getMessage(), toString(), printStackTrace(), etc.
Error : erreurs graves, abandon du programme
Exception : anomalies récupérables
RunTimeException : erreur à l’exécution
ArithmeticException : division par zéro par exemple
ClassCastException : mauvaise conversion de classes (cast)
IndexOutOfBoundsException : en dehors des limites (tableau)
NullPointerException : référence nulle
IllegalArgumentException
NumberFormatException : nombre mal formé
IOException : erreurs d’entrées-sorties
FileNotFoundException : fichier inconnu

5
 Dans un catch, on peut capter l’exception à son niveau le plus général (Exception),
ou à un niveau plus bas (FileNotFoundException par exemple) de façon à avoir un
message plus approprié. On peut avoir plusieurs catch pour un même try.

DEFINIR SA PROPRE EXCEPTION

Si on veut pouvoir signaler ou traiter, un événement exceptionnel, généralement non


souhaité, d'un type non prévu par l'API, il faut définir une nouvelle classe étendant la classe
java.lang.Exception ; la classe étendue ne contient en général pas d'autre champ qu'un (ou
plusieurs, ou zéro) constructeur(s) et une redéfinition de la méthode toString. Lors du lancement
de l'exception, (à l'aide du mot réservé throw comme nous le verrons dans le prochain
exemple), on crée une instance de la classe définie.
Voilà une classe héritant de la classe Exception que nous utiliserons dans les exemples
suivants.

public class ExceptionRien extends Exception {


int nbChaines;
public ExceptionRien(int nombre) {
nbChaines = nombre;
}
public String toString() {
return "ExceptionRien : aucune des " + nbChaines + " chaines n'est valide";
}
}

LANCER UNE EXCEPTION

L'objectif de l'exemple est d'écrire une méthode moyenne qui calcule la moyenne
d'entiers reçus en paramètre par un tableau de chaînes de caractères. Les chaînes ne
représentant pas un entier (et donc erronées) doivent être ignorées. Néanmoins, on veut de
plus que la méthode moyenne lance une exception de type ExceptionRien si aucune chaîne de
caractères n'est valide afin d'éviter la division par zéro. Une méthode main dans la classe
EssaiLance permet de tester la méthode moyenne de la classe Lance.

6
public class Lance {
static int moyenne(String[] liste) throws ExceptionRien {
int somme = 0, nbEntiers = 0;
for (String chaine : liste) {
try {
somme += Integer.parseInt(chaine);
nbEntiers++;
}
catch (NumberFormatException e) {
System.out.println(chaine + " n'est pas entier");
}
}
if (nbEntiers == 0) throw new ExceptionRien(liste.length);
return somme/nbEntiers;
}
}
class EssaiLance {
public static void main(String[] arg) {
try {
System.out.println("La moyenne est " + Lance.moyenne(arg));
}
catch (ExceptionRien e) {
e.printStackTrace();
}
}
}

Exemples de résultats d’exécution :


Pour :

java EssaiLance ha 15.5

On obtient :

ha n'est pas entier


15.5 n'est pas entier
ExceptionRien : aucune des 2 chaines n'est valide
at Lance.moyenne(Lance.java:15)
at EssaiLance.main(Lance.java:23)

7
throws ExceptionRien : la méthode moyenne indique ainsi qu'il est possible qu'une de ses
instructions envoie une exception de type ExceptionRien sans que celle-ci soit attrapée par un
mécanisme try-catch. Il est obligatoire d'indiquer ainsi un éventuel lancement d'exception non
attrapée, sauf pour les exceptions les plus courantes de l'API. Si vous oubliez de signaler par la
clause throws l'éventualité d'un tel lancement d'exception, le compilateur vous le rappellera.

throw new ExceptionRien(liste.length) : on demande ainsi le lancement d'une instance de


ExceptionRien en lui donnant comme paramètre le nombre de chaînes du tableau traité. Une
fois lancée, l'exception se propagera comme expliqué dans le cours. Ici, l'instruction :
return somme/nbEntiers; n'est pas exécutée, la méthode moyenne se termine, on se retrouve
alors à l'appel de la méthode moyenne dans le main, la concaténation dans le paramètre de la
méthode println n'est pas calculée, la méthode println n'est pas utilisé, le bloc try dans la
méthode main se termine ; le bloc catch qui suit attrape les ExceptionRien(s) : l'instruction de
ce bloc catch est effectuée. Le programme reprend alors son exécution (pour se terminer).

e.printStackTrace(); : la méthode printStackTrace est héritée de la classe java.lang.Throwable


(on rappelle que la classe ExceptionRien hérite de la classe java.lang.Exception qui hérite de la
classe java.lang.Throwable). Cette méthode écrit sur la sortie standard d'abord l'exception e
grâce à sa méthode toString, puis la pile des méthodes traversées par l'exception, comme on
peut le voir sur la sortie de l'exemple.

AUTRES PROPAGATIONS D'EXCEPTIONS

Ces deux exemples n'apportent rien de nouveau. Il reste juste à savoir que la classe
Exception possède un constructeur prenant en paramètre une chaîne de caractères et que la
méthode getMessage de la classe Exception renvoie cette chaîne de caractères. Vous pouvez
aussi constater que plusieurs blocs catch peuvent se succéder eu attrapant des exceptions de
types différents.

Exemple 1

Essayez de répondre aux deux questions suivantes :

8
 Que donne ce programme lancé avec :

java EssaiMoyenne ha 2 -3 27 18

 Que donne ce programme lancé avec :

java EssaiMoyenne ha -3

class ExceptionIntervalle extends Exception {


ExceptionIntervalle(String s) {
super(s);
}
}

class Moyenne {
static int moyenne(String[] liste) throws ExceptionRien {
int somme = 0,entier, nbEntiers=0;
int i;

for (String chaine : liste) {


try {
entier = Integer.parseInt(chaine);
if (entier < 0) throw new ExceptionIntervalle("petite");
if (entier>20) throw new ExceptionIntervalle("grande");
somme += entier;
nbEntiers++;
}
catch (NumberFormatException e) {
System.out.println(chaine + " n'est pas entier");
}
catch (ExceptionIntervalle e) {
System.out.println(chaine + " est trop "+ e.getMessage()); }
}
if (nbEntiers == 0) throw new ExceptionRien(liste.length);
return somme/nbEntiers;
}
}

class EssaiMoyenne {
public static void main(String[] arg) {
try {
System.out. println("La moyenne est "+ Moyenne.moyenne(arg));
}
catch (ExceptionRien e) {
e.printStackTrace();
}
}
}

9
Exemple 2

Essayez de répondre aux deux questions suivantes :

 Que donne ce programme lancé avec :

java EssaiAttrape ha 15 12

 Que donne ce programme lancé avec :

java EssaiAttrape ha 15.5

class Attrape {

public static int moyenne(String[] liste) {


int somme = 0, nbEntiers = 0;
for (String chaine : liste) {
try {
somme += Integer.parseInt(chaine);
nbEntiers++;
System.out.println(" Instruction de la chaine " +chaine + " est exécutée");
} catch (NumberFormatException e) {
System.out.println ("Exception : " + e);
System.out.println(chaine + " n'est pas entier");
}
}
System.out.println("Instruction après bloc catch exécutée");
return somme / nbEntiers;
}
}

public class EssaiAttrape {


public static void main(String[] arg) {
try{
System.out.println("La moyenne est " + Attrape.moyenne(arg));
System.out.println("Instruction de main exécutée après l'instruction erroné " );}
catch (ArithmeticException a)
{System.out.println ("Exception : " + a);
a.printStackTrace();}
System.out.println("Instruction de main exécutée après le bloc catch " );
}
}

10

Vous aimerez peut-être aussi