• Aucun résultat trouvé

Programmation objet avancée

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation objet avancée"

Copied!
23
0
0

Texte intégral

(1)

Programmation objet avancée

Les exceptions

(2)

Plan

Principes.

Classes d'exception.

La « propagation » des exceptions.

Définir une classe d'exception.

(3)

Principes

Lorsqu'un cas d'erreur intervient dans une méthode :

façon C : retour d'une valeur négative ou NULL, 

façon Java/C++ : génération d'un objet exception.

Problème : « capter » cet objet quand il existe et sinon, continuer l'exécution.

Solution : syntaxe spéciale try/catch.

try {

// instructions }

catch(ClasseException e) {

// traitement de l'objet exception e

(4)

Principes

Mise en place (minimale) :

on englobe une suite de N instructions dans try{}

certaines (<= N) vont potentiellement générer des instances de M (>= 1) classes d'exceptions différentes.

après la fermeture du try, on met M blocs catch, permettant chacun de traiter un des types d'exception.

(5)

Principes

Exemple n°1 de try/catch

...ObjectInputStream ois = null;

Double d = null;

try {

ois = new ObjectInputStream(new FileInputStream("toto.txt"));

d = (Double)(ois.readObject());

}

catch(IOException e) {

System.out.println("pb accès fichier : "+e.getMessage());

}

catch(ClassNotFoundException e) {

System.out.println("pb de classe : "+e.getMessage());

}System.out.println("après try/catch");

(6)

Principes

Fonctionnement :

les instructions du bloc try sont exécutées jusqu'à la génération d'une exception ou sinon jusqu'à la fin du bloc.

pas d'exception : l'exécution continue après le dernier bloc catch,

exception générée :

l'exécution saute jusqu'au catch associé au type d'exception,

exécution des instructions du catch,

l'exécution continue après le dernier bloc catch.

(7)

Principes

Retour sur l'exemple n°1 :

cas sans aucune exception :

entrée dans le try,

exécution des 2 instructions,

sortie du try : saut après les catch,

affichage de : après try/catch.

(8)

Principes

Retour sur l'exemple n°1 :

cas exception à la 1ère instruction :

entrée dans le try,

exécution instruction 1,

par ex. fichier inexistant Þ génération IOException,

saut immédiat au catch(IOException),

exécution instructions du catch,

saut après les catch,

affichage de : après try/catch.

(9)

Principes

Remarques :

exception générée par une instruction Þ les instructions suivantes ne seront jamais exécutées.

si plusieurs catch, le premier rencontré associé au type d'exception est exécuté

si un catch exécuté, les autres catch ne seront jamais exécutés Þ suite de catch similaire à une structure if … else if … else if …

(10)

Les classes d'exception

2 types :

vérifiées (= checked) : une méthode qui génère ce type oblige le programmeur à mettre son appel dans un try/catch.

non vérifiées (= unchecked) : pas de try/catch obligatoire.

exception non vérifiées = exceptions difficilement prévisibles :

accès à un objet indéfini (NullPointerException), 

erreur arithmétique (ArithmeticException),

(11)

Les classes d'exception

Exemple n°2 : exception non vérifiée

try { ...

d = (Double)(ois.readObject());

double dd = 5.0/d; // si d=0, génération ArithmeticException }

catch(IOException e) {

System.out.println("pb accès fichier : "+e.getMessage());

}

catch(ClassNotFoundException e) {

System.out.println("pb de classe : "+e.getMessage());

}

System.out.println("après try/catch");

ArithmeticException = type non vérifé

(12)

Les classes d'exception

Exemple n°3 : oubli catch exception vérifiée

try { ...

d = (Double)(ois.readObject());

}catch(IOException e) {

System.out.println("pb accès fichier : "+e.getMessage());

}

System.out.println("après try/catch");

ClassNotFoundException = type vérifé

Þ erreur de compilation :

error: unreported exception ClassNotFoundException; must be caught or declared to be thrown

(13)

Créer une méthode lanceuse d'exceptions

Principes:

Ajouter throws … dans l'entête de la méthode

La liste après throws contient le nom des classes d'exception qui peuvent être générées par la méthode.

Dans le corps de la méthodes, si un cas d'erreur survient, on utilise throw (sans le s terminal) sur une instance de la classe d'exception désirée.

(14)

Créer une méthode lanceuse d'exceptions

Example n°4: (sur une classe personnalisée de liste chaînée)

class LinkedList { Cell head;

int listSize;

...

public Cell replace(int index, Cell c) throws IndexOutOfBoundsException,NullPointerException {

if (c == null) throw new NullPointerException();

if ((index < 0)||(index >= listSize)) { throw new IndexOutOfboundException();

} ...

} ...

}

(15)

La propagation des exceptions

Exemple n°5 : propagation implicite d'except. non vérifiées

class A { ...

private B b;

...

public void methodeA() { b.methodeB();

} ...

}

class B { ...

public void methodeB() { int[] tab = new int[10];

//gén. d'une IndexOutOfBoundException tab[25] = 3;

} ...

}

class Exemple4 { ...

public static void main(String[] args){

A a = new A();

a.methodeA();

...

(16)

La propagation des exceptions

Remarques sur l'exemple n°5 :

main() appelle methodeA() qui appelle methodeB().

methodeB() génère IndexOutOfBoundException

cette exception n'est pas captée par methodeB() Þ elle est propagée à la méthode qui l'a appelé, i.e. methodeA()

methodeA() ne capte pas non plus l'exception Þ elle est propagée à la méthode qui l'a appelé, i.e. main()

main() ne capte pas plus l'exception Þ la JVM met fin à l'exécution du programme.

(17)

La propagation des exceptions

Exemple n°6 : propagation explicite d'exception vérifiée

class A {

private B b;

...

public void methodeA() { try { b.methodeB();}

catch(IOException e) { ... } }

}

class B {

FileReader fr = null;

...

public void methodeB() throws IOException { //gén. possible d'une IOException

fr = new FileReader("toto.txt");

...

class Exemple5 { ...

public static void main(...){

A a = new A();

a.methodeA();

...

} }

ajout

(18)

La propagation des exceptions

Remarques sur l'exemple n°6 :

normalement methodeB() devrait utiliser try/catch pour entourer new FileReader(...)

l'ajout de throws IOException permet de contourner cette obligation mais …

s'il y a exception, elle n'est pas captée par methodeB() Þ elle est propagée à la méthode qui l'a appelé, i.e.

methodeA()

methodeA() capte l'exception Þ la propagation s'arrête là.

Si methodeA() n'utilise pas try/catch Þ erreur compilation

(19)

La propagation des exceptions

Remarques sur l'exemple n°6 (suite):

on pourrait ajouter throws IOException dans l'entête de methodeA() pour qu'elle propage l'exception à main().

dans ce cas, c'est dans main() qu'il faudrait un try/catch, sinon erreur compilation.

Þ explicite = propagation choisie par le programmeur

(20)

La propagation des exceptions

Pour résumer :

Capturer les exceptions non vérifiées = mauvaise idée. Il faut utiliser la propagation implicite pour que le programme plante Þ bugs classiques (objet null, mauvais index, …) plus facile à détecter.

Utiliser la propagation explicite quand un objet ne peut traiter lui-même l'exception Þ analogie avec le traitement administratif d'un problème : “Si je n'ai pas la connaissance/le pouvoir pour résoudre le problème, je le relaie à mon chef”.

(21)

Créer des classes d'exception

Principes:

Hériter de Exception ou une autre classe existante.

Customiser le message associé à l'exception :

le constructeur appelle le super-constructeur avec un message spécial.

et/ou redéfinir la méthode getMessage(). Remarques:

la classe peut avoir des attributs, initialisés à la construction,

(22)

Créer des classes d'exception

Exemple n°7: (sur une classe personnalisée de liste chaînée)

class ListAccessException extends IndexOutOfBoundException { int index;

LinkedList list;

public ListAccessException(LinkedList list, int index) { super("Invalid cell index ["+index+"]");

this.index = index;

this.list = list;

}

public String getMessage() { String msg;

if (index>=list.size()) msg="Index greater than list size";

else if (index < 0) msg="Negative cell index";

return msg;

}

(23)

Créer des classes d'exception

Exemple n°7 (suite):

class LinkedList { Cell head;

int listSize;

...

public Cell get(int index) throws ListAccessException { if ((index < 0)||(index >= listSize)) {

throw new ListAccessException(this,index);

} ...

} ...

}

Références

Documents relatifs

• Usage des annotations pour indiquer les méthodes de test et autres

• Les dépendances indiquent le couplage (qui peut être faible) entre 2 classes.. • Réduction

La déclaration de la classe sera écrite dans un fichier d'en-tête (.h), contenant éventuellement quelques petites fonctions en ligne. Le corps des fonctions membres de cette

Si le programme appelant ne fait rien, le lancement d ’une exception appelle la fonction standard abort qui met fin au programme. Note : sous Borland C++ la fonction

Par exemple : std::string , qui obligatoirement doit faire des allocations de mémoire (pour stocker les caractères) et donc libérer, quoi qu'il arrive, même en cas d'exception

Plusieurs instances de cette classe devront référencer le même objet en mémoire : définition d'une sous-classe assistante, associant l'adresse réelle de l'objet et un compteur...

Une pile représente un ensemble de données où l'on ne peut accéder qu'au dernier élément entré, qui devient donc le premier à sortir. On les appelle parfois LIFO (last in

A présent le code peut s'utiliser pour afficher tous les éléments d'une liste d'entiers différents de -5, tous les éléments d'un tableau de chaînes de moins de trois