Dans tout programme, il y a des erreurs d'exécution possibles , des
cas particuliers qui n'ont pas forcément été traités. On ne vise pas à les
supprimer, mais à les controler (robustesse du code, tolérance aux
erreurs)
il s'agit d'erreurs d'exécution, pas d'erreur de programmation que le compilateur peut
détecter.
Exemple : un fichier que le programme essaie de lire est déjà utilisé par une autre
application
Quand il y a une erreur, on voudrait se retrouver dans un endroit du
programme d’où l’on peut récupérer de l’erreur :
Exemple : une méthode utilise un nombre passé en paramètre, nombre par lequel on
divise un autre nombre. Ce nombre est donné par l'utilisateur. Si ce nombre vaut 0,
on veut que l'erreur qu'il déclenche soit traitée au niveau de l'interaction avec
l'utilisateur, et non à l'intérieur de la méthode.
L'erreur doit donc pouvoir être propagée et véhiculer une description
pour être traitée en dehors du contexte où elle s'est produite
=> Exception
Une erreur qui lève
une exception
Un contexte
d’exécution
Le contexte
d’exécution qui
attrape l’exception
saut
Un programme qui rencontre une erreur doit en transférer le traitement à une
autre partie (“exception handler”) et lui donner une valeur qui décrit l’erreur
(l’“exception” proprement dite)
Le principe d’endiguement :
Un programme est une hiérarchie de contextes d’ecution
Une erreur n’est visible qu’à l’intérieur d’un contexte dans cette hiérarchie
Une routine de récupération existe à l’interface d’un contexte d’exécution,
pour que l’erreur ne se propage pas vers un niveau plus elevé
Checked exceptions : exceptions déclarées, traitées ou propagées par
le code (comportement exceptionnel mais prévu). Le compilateur vérifie
que les méthodes ne lèvent que les exceptions déclarées pour la classe.
Unchecked exceptions : exceptions non traitées et non propagées dans
le code. Le compilateur ne les vérifie pas (comportement non prévu).
Elles héritent de RuntimeException et Error.
Object
Throwable
Exception Error
RuntimeException StackOverFlowError
OutOfMemoryError
VirtualMachineError
ClassNotFoundException AWTException
ArithmeticExceptionNullPointerException
...
...
...
Les exceptions sont lancées par le mot clé throw. Une méthode
dans le corps de laquelle une exception est lancée doit le signaler
par un bloc throws.
Si l'exception remonte jusqu'à la JVM, le thread qui a lancé
l'exception est interrompu
public static void parseFile(String fileName) throws FileNotFoundException,
ParseException,IOException{
File f = new File(fileName);
BufferedReader stream = new BufferedReader(new InputStreamReader(new
FileInputStream(f)));
// FileInputStream peut lancer une FileNotFoundException
// readLine peut lancer une IOException
if(!stream.readLine().equals("file header")) throw new
ParseException("Entête de fichier incorrecte ligne 1",0);
else{
...
}
}
public void static main(String[] args) throws FileNotFoundException{
MyClass.parseFile("MyFile");
}
try{
// contexte d'exécution. Peut contenir une instruction (méthode) qui lance une exception.
MyClass.parseFile("MyFile");
...
}
catch(FileNotFoundException e){
System.out.println(e.getMessage());
}
catch(ParseException e){
e.printStackTrace(System.out);
}
catch(IOException e){
System.out.println("Problème d'accés fichier");
}
finally{
// optionnel. Bloc exécuté quelque soit les cas (exception levée ou pas). Il sert à faire le
// ménage, fermer des fichiers ouverts dans le bloc try par exemple
}
Un seul bloc catch est exécuté, le premier rencontré qui correspond au type de
l'exception. Attention : si on essaie de récupérer une exception déjà récupérée
dans un bloc catch précédent (surclassée par exemple), le compilateur gueule
(il ne sait plus quel traitement appliquer)
Si une exception est levée dans un constructeur, l'objet n'est pas
créé. Cela permet de contrôler les paramètres du constructeur
public class GroupeEtudiants{
private int nbEtudiants;
public GroupeEtudiants(int nb) throws IllegalArgumentException{
if(nb < 1) throw new IllegalArgumentException("Trop peu d'étudiants!");
else this.nbEtudiants = nb;
}
public static void main(String[] arg){
GroupeEtudiants ge;
try{
ge = new GroupeEtudiants(0);
System.out.println("Premier groupe " + ge);
}
catch(IllegalArgumentException e){System.out.println("Echec");}
try{
ge = new GroupeEtudiants(4);
System.out.println("Deuxième groupe " + ge);
}
catch(IllegalArgumentException e){System.out.println("Echec");}
}
}
Il suffit de sous classer la classe Exception
/** Exception lancée en cas de clic sur un bouton */
public class ButtonException extends Exception{
public ButtonException(){
super("Button clicked");
}
}
C’est très mauvais d’utiliser les exceptions pour modifier l’ordre d’exécution
dans une situation normale (ralentissement, non sérialisation des
comportements, ...)
Attention au bon usage des exceptions :
les exceptions doivent être exceptionnelles
ce ne sont pas des structures de contrôle!
éviter de capter les erreurs graves du style NullPointerException, il vaut mieux
les propager
On peut toujours utiliser Exception, mais il vaut mieux utiliser la classe la plus
précise, pour avoir le maximum d'info sur l'erreur, et en plus les traitements au dessus
dépendent du type donc pour mieux canaliser et traiter l'erreur, faut préciser
Trouver la fin d’un flux est tout à fait normal, ce n’est pas une erreur!
La sortie d'un bloc try se produit quand :
le bloc se termine normalement
une exception est levée et interrompt l'exécution du bloc
le bloc exécute une instruction return, break ou continue
Dans tous les cas, le bloc finally, s'il existe, est
obligatoirement exécuté après
try {
for (;;) process (stream.next());
}
catch(ExceptionType1 e){...}
...
finally{stream.close();}
try {
for (;;) process (stream.next());
}
catch(StreamEndException e){stream.close();}
En programmation objet, l'idée de réutilisabilité est essentielle. On peut
réutiliser le code facilement car il est structuré en briques élémentaires,
les classes
On veut pouvoir aussi réutiliser les données créées par un programme,
il faut donc non plus sauver les classes (descriptions communes d'un
ensemble d'objets) mais les objets eux-mêmes qui encapsulent des
valeurs d'attributs
Principe de la sérialisation : il s'agit de permettre la persistance des
objets, c'est-à-dire que la durée de vie de l'objet est supérieure à celle
du programme qui l'a créé. L'objet est sauvegardé dans un flux et
pourra être reconstitué plus tard dans l'état où il a été sauvegardé. On
sauve donc les valeurs de ses attributs et la manière de recréer l'objet
Applications :
stockage de données structurées
échanges d'objets entre applications distribuées
RMI (Remote Method Interface) : permet d'utiliser des objets distants (ne s'exécutant
pas sur la même JVM). Les objets sont transmis par sérialisation.
Beans
Tout objet implémentant l'interface Serializable est sérialisable
dans un flux (fichier,seau, ...)
Serializable n'a aucune méthode, elle ne sert qu'à identifier les objets
sérialisables
La sérialisation est effectuée par writeObject(Object o),
méthode de l'interface ObjectOutput
généralement, on utilise un ObjectOutputStream, classe qui implémente
ObjectOutput
Dans l'implémentation ObjectOutputStream, o doit implémenter
Serializable sinon une NotSerializableException est levée
peut lancer une IOException en cas de problème d'accès au flux
la sérialisation d'un objet orialise également tous les objets référencés par o
(ces objets doivent donc être sérialisables sinon exception!)
1 / 9 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !