gestion des exception
Status:
Tags: <% tp.file.cursor(3) %>
Links: <% tp.file.cursor(4) %>
Gestion des exception
<% tp.file.cursor(5) %>
introduction
Souvent, un programme doit traiter des situations inattendues (exceptionnelles) en dehors de sa tache principale.
Une situation exceptionnelle peut être assimilée à une erreur qui génère une interruption gérée habituellement par le système d’exploitation.
Exemples d’erreurs/exceptions courantes :
Accès non autorisé à une zone mémoire (erreur de manipulation de pointeur), division par zéro, débordement d'indices dans une collection, etc
Exemple 1
public class TestSansException {
public static void main(java.lang.String[] args) {
int i = 3;
int j = 0;
System.out.println("Avant exception");
System.out.println("résultat = " + (i / j));
System.out.println("ne sera jamais exécutée !");
}
}
Lors de l’exécution, la JVM va générer cette erreur (exception) java.lang.ArithmeticException: / by zero Et le programme TestSansException sera interrompu.
Definition
Une exception est un événement, se produisant lors de l’exécution d’un programme, qui interrompt l’enchaînement normal des instructions.
L’objectif est de gérer ces exceptions par le programme lui-même en les interceptant (en les capturant ).
Le principe consiste à repérer les morceaux de code (par exemple, une division ) qui pourraient générer une exception, de capturer l'exception correspondante et enfin de la traiter, c'est-à-dire d'afficher un message personnalisé et de continuer l'exécution.
Les exceptions représentent un mécanisme de gestion des erreurs Il se compose de (en java) :
- Objets représentant les erreurs
- Un ensemble de trois mots clés (une instruction) qui permettentde détecter et de traiter ces erreurs ('try', 'catch' et 'finally' )
et - Un moyen de les lever ou les propager (throw et throws).
Ce mécanisme permet de renforcer la fiabilité des programmes
Gestion des exceptions en java
En Java, on distingue trois types d'erreurs :
Les erreurs grave
- Les erreurs graves qui causent généralement l'arrêt du programme et qui sont représentées par la classe
java.lang.Error
.
Exemple : OutOfMemoryError
Les erreurs qui doivent généralement être traitées
- Les erreurs qui doivent généralement être traitées et qui sont représentées par la classe
java.lang.Exception
.
Exemple : FileNotFoundException
Les erreurs qui peuvent ne pas être traitées
- Les erreurs qui peuvent ne pas être traitées et qui sont des objets de la classe java.lang.RuntimeException qui hérite de
java.lang.Exception
.
Exemple : ArrayIndexOutOfBoundsExceptions
Instruction try/catch/finally
Le bloc «try» rassemble les blocs d’instructions susceptibles de produire des erreurs ou des exceptions.
try {
bloc_susceptible_de_produire_des_erreurs
} catch (type_exception_1 arg_1) {
bloc_1
} catch (type_exception_2 arg_2) {
bloc_2
}...
} finally {
bloc_optionnel_qui_s_exécute_toujours
}
Finally
- La clause « finally » définit un bloc qui sera toujours exécuté, qu'une exception soit levée ou non.
- Ce bloc est facultatif.
Exemple : Instruction try/catch/finally
public class TestException {
public static void main(java.lang.String[] args) {
int i = 3; int j = 0;
try {
System.out.println("résultat = " + (i / j));
} catch (ArithmeticException e) {
System.out.println(" Attention ! Division par 0");
}
System.out.println("s’exécute sans problème");
}
}
Instruction try/catch/finally
public class TestException {
public static void main(java.lang.String[] args) {
int i = 3; int j = 0;
try {
System.out.println("résultat = " + (i / j));
} catch (ArithmeticException e) {
System.out.println("getmessage : " + e.getMessage());
System.out.println("toString : " + e.toString());
System.out.println("printStackTrace : " );
e.printStackTrace());
}
System.out.println("s'excute sans problème");
}
}
Méthodes de l’objet Exception
getmessage() affiche le message de l’exception levée (e.g. / by zero).
toString() affiche en plus le nom complet de cette classe exception (e.g. java.lang.ArithmeticException
: / by zero).
printStackTrace() : affiche l'état de la pile lors de la remontée de l'exception. Utile pour trouver les causes de celle-ci.
java.lang.ArithmeticException
: / by zero
at TestException.main(TestException.java:7)
at __SHELL39.run(__SHELL39.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessor
Impl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethod AccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at bluej.runtime.ExecServer$3.run(ExecServer.java:730)
Exemple de propagation de l’exception
class Propagation {
public static void m1() { m2(); }
public static void m2() { m3(); }
public static void m3() {throw new RuntimeException();}
public static void main(String[] args) {
m1();
} // end of main()
}
java.lang.RuntimeException
at Propagation.m3(Propagation.java:4)
at Propagation.m2(Propagation.java:3)
at Propagation.m1(Propagation.java:2)
at Propagation.main(Propagation.java:6)
UABB-Tlemcen – Département d’Informatique - cours de POO 2 pour Ing. 2
Quelques exceptions prédéfinies
Il existe en java des exceptions prédéfinies :
- ArithmeticException : levée lorsqu’une condition arithmétique exceptionnelle se produit. Par exemple, elle se manifeste lors d’une division par zéro.
- NullPointerException : elle se manifeste lorsqu’on cherche à utiliser un objet ou un tableau non initialisé (sur lequel on n’a pas fait de new.
- ArrayIndexOutOfBoundsException : il s’agit d’une erreur sur l’indice d’un tableau. On cherche à accéder à une case qui n’existe pas.
Exemple d’exceptions prédéfinies
class Exemple3{
static int[] tableau = {17, 12, 15, 38, 29, 157, 89, -22, 0, 5};
static int division(int indice, int diviseur){
return tableau[indice]/diviseur;
}
public static void main(String[] args){
int x, y;
boolean ok = true;
Integer i;
java.util.Scanner scan = new java.util.Scanner(System.in);
do{
System.out.print("Entrez l’indice de l’entier a diviser: ");
x = scan.nextInt();
System.out.print("Entrez le diviseur: ");
y = scan.nextInt();
System.out.println("Le resultat de la division est: ");
System.out.println(division(x,y));
i=null;
if (y==1) {i=y;ok=true;}
System.out.print("Objet initialisé : "+i.toString());
}while(!ok);
}
}
Aussi
- Il est possible de créer ses propres exceptions et de les lancer (throw) lors de l’exécution d’un programme.
- Pour créer sa propre classe d’exception, il suffit donc de créer une classe qui hérite de
java.lang.Exception
Exemple
class Point {
public static final int X_MAX = 1024, Y_MAX = 768;
private int x, y;
public Point (int a, int b) {
x = a;
y = b;
}
}
Créer son propre type d'exception
en héritant de la classe Exception
class CoordonneesIllegalesException extends Exception {
public CoordonneesIllegalesException () {
super("Coordonnées illégales."); }
public CoordonneesIllegalesException (String msg) {
super(msg); }
}
}
Lancer une exception
Une exception peut être lancée via la syntaxe suivante :
throw exception;
où exception est une expression dont la valeur doit être un objet de type Throwable.
class Point {
public static final int X_MAX = 1024, Y_MAX = 768;
private int x, y;
public Point (int a, int b) throws CoordonneesIllegalesException{
if (a < 0 || a > X_MAX || b < 0 || b >= Y_MAX) {
throw new CoordonneesIllegalesException("Coordonnées illégales.");
}
x = a;
y = b;
}
}
public class TestException3 {
public static void main(java.lang.String[] args) {
try {
Point p = new Point (-1, 5);
} catch(CoordonneesIllegalesException e) {
System.out.println(e.getMessage());
}
}
}
Remarque
Si un événement indésirable survient dans le bloc try, la partie éventuellement non exécutée de ce bloc est abandonnée et le premier bloc catch est traité.
Exemple:
try {
System.out.print("Entrez l’indice de l’entier a diviser: ");
x = scan.nextInt();
System.out.print("Entrez le diviseur: ");
y = scan.nextInt();
Dans cet exemple, les instructions qui suivent dans le bloc try:
System.out.print("Entrez le diviseur: ");
y = scan.nextInt();
-
Ne sont pas exécutées.
Même l’instruction en cours "scan.nextInt();" -
Est abondannée.
-
Sans consommer cette entrée invalide, le scanner reste bloqué sur cette entrée.
-
throws
indique qu'une méthode peut potentiellement lancer une exception vérifiée (checked).
Son utilité réside dans le fait qu'elle transmet la responsabilité de la gestion de cette exception à l'appelant de la méthode, plutôt que de la traiter localement dans la méthode elle-même.
Checked exceptions, also known as compile-time exceptions, are exceptions that must be either caught or declared in the method signature using the throws keyword.
These exceptions are typically used to handle expected error scenarios that a program can recover from..
Utilisation de throws :
Transparence des exceptions : déclare et informe explicitement les développeurs qui utilisent la méthode qu'elle peut lancer une exception particulière.
Définition de la responsabilité la responsabilité de la gestion de ces exceptions incombe à l'appelant.
Propagation des exceptions : propager les exceptions vers des niveaux supérieurs dans la pile d'appels..
La classe Throwable
La classe de base pour le traitement des erreurs.
Dans le constructeur Throwable(String) :
La chaîne en paramètre permet de définir un message qui décrit l'exception
==String getMessage( ) ==: retourne le message
==void printStackTrace( ) ==: affiche l'exception et l'état de la pile d'exécution au moment de son appel.
Multiples exceptions dans une clause catch
Il n'est pas rare d'avoir à dupliquer les mêmes lignes de code dans le bloc de code de plusieurs clauses catch().
try {
// traitements pouvant lever les exceptions
} catch(ExceptionType1 e1) {
// Traitement de l'exception
} catch(ExceptionType2 e2) {
// Traitement de l'exception
} catch(ExceptionType3 e3) {
// Traitement de l'exception
}
A partir de Java 7, la même portion de code est simplifiée : il suffit de déclarer les exceptions dans une même clause catch en les séparant par le caractère "|".
try {
// traitements pouvant lever les exceptions
} catch(ExceptionType1|ExceptionType2|ExceptionType3 ex) {
// Traitement de l'exception
}
Si plusieurs types d'exceptions sont déclarés dans une clause catch alors la variable qui permettra un accès à l'exception concernée est implicitement déclarée final.
try et la gestion des ressources
- Les ressources comme des fichiers, des flux, des connexions, etc. doivent être fermées.
- Utilisation du bloc finally pour la fermeture.
- Il faut noter que les classes (les ressources) qui implémentent l'interface Closeable peuvent être utilisées comme ressource dans une instruction try. Car elles sont fermées automatiquement.
L'instruction try-with-resources (Avant Java 7)
Des ressources comme des fichiers, des flux, des connexions, ...
doivent être fermées explicitement par le développeur pour libérer les ressources sous-jacentes qu'elles utilisent.
Généralement cela est fait en utilisant un bloc try / finally pour garantir leur fermeture dans la quasi-totalité des cas.
Fermer explicitement la ressource implique un risque potentiel d'oubli de fermeture qui entraine généralement une fuite de ressources.
Exemple de fuite de ressources :
- Fuite de mémoire: Si une ressource mémoire n'est pas libérée après son utilisation, cela peut entraîner une consommation continue de mémoire., ce qui peut éventuellement conduire à un épuisement de la mémoire disponible et au plantage du programme ou du système.
- Fuite de fichiers: Si un programme ouvre un fichier mais ne le ferme pas correctement après l'avoir utilisé, cela peut entraîner l'impossibilité d'ouvrir de nouveaux fichiers ou de faire fonctionner d'autres opérations d'I/O de manière fiable.
- Fuite de connexions réseau: Dans le cas des connexions réseau, si une connexion réseau n'est pas correctement fermée après son utilisation, cela peut entraîner l'épuisement des ressources réseau disponibles.
Avec Java 7, le mot clé try peut être utilisé pour déclarer une ou plusieurs ressources.
Une nouvelle interface a été définie pour indiquer qu'une ressource peut être fermée automatiquement :
java.lang.AutoCloseable
Tous les objets qui implémentent l'interface AutoCloseable peuvent être utilisés dans une instruction de type try-with-resources. Cette dernière garantit que chaque ressource déclarée sera fermée à la fin de l'exécution de son bloc de traitement.
L'interface java.lang.Autocloseable
possède une unique méthode close()
qui sera invoquée pour fermer automatiquement la ressource encapsulée par l'implémentation de l'interface.
L'interface java.io.Closable introduite par Java 5 hérite de l'interface AutoCloseable : ainsi toutes les classes qui implémentent l'interface Closable peuvent être utilisées comme ressource dans une instruction try-with-resource.
Exemple de L'instruction try-with-resources
try (BufferedReader bufferedReader = new BufferedReader(new FileReader("monfichier.txt"))) {
String ligne=null;
while ((ligne = bufferedReader.readLine()) != null) {
System.out.println(ligne);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
L'instruction try-with-resource présente un petit inconvénient : il est obligatoire de définir la variable qui encapsule la ressource entre les parenthèses qui suivent l'instruction try. Il n'est par exemple pas possible de fournir en paramètre de
l'instruction try une instance déjà créé.
public static void afficherFichier(Reader flux) throws IOException {
try (Reader closeableReader = flux) {
int donnee;
while ((donnee = flux.read()) >= 0) {
System.out.print((char) donnee);
}
}
Dans l'exemple ci-dessus, comme la variable définie et celle existante pointent sur la même référence, les deux variables.
peuvent être utilisées indifféremment. L'instruction try-with-resource se charge de fermer automatiquement le flux.
Voir Exemple de la classe TestCloseRessource
Une exception chaînée est une fonctionnalité qui permet à une exception d'être associée à une autre exception en tant que sa cause.
- Il est important de conserver des informations sur toutes ces exceptions pour un traitement ultérieur.
- En Java, la classe Throwable possède une méthode appelée getCause() qui permet d'obtenir la cause de l'exception actuelle.
- Cela permet de former une chaîne d'exceptions, où une exception peut avoir une autre exception comme sa cause.
Exemple de la classe ExceptionChainee
class ExceptionA extends Exception {
public ExceptionA(String message, Throwable cause) {
super(message, cause);
}
}
class ExceptionB extends Exception {
public ExceptionB(String message) {
super(message);
}
}
public static void methodeB() throws ExceptionB {
// Simuler une exception
throw new ExceptionB("Exception B s'est produite.");
}
} //fin du main
public static void methodeA() throws ExceptionA {
try {
// Appeler une autre méthode qui peut lever une exception
methodeB();
} catch (ExceptionB e) {
// Lancer une nouvelle exception en chaînant l'exception
// précédente
throw new ExceptionA("Exception A s'est produite.", e);
}
}
public class ExceptionChainee {
public static void main(String[] args) {
try {
// Appeler une méthode qui peut lever une exception
methodeA();
} catch (ExceptionA e) {
// Attraper l'exception et afficher la cause, si elle existe
Throwable cause = e.getCause();
if (cause != null) {
System.out.println("Cause de l'exception : " + cause.getMessage());
} else { System.out.println("Aucune cause trouvée."); }
}
}
Explication
La methodeA() appelle methodeB(), qui peut lever une ExceptionB.
Lorsque ExceptionB est attrapée dans methodeA(), une nouvelle ExceptionA est lancée en chaînant l'exception précédente (ExceptionB) en tant que cause.
Dans le bloc catch dans main(), nous utilisons getCause() pour obtenir la cause de ExceptionA et afficher son message.
Application Gestion des exception
type 1
type 1
type 1
Criticisms Gestion des exception
type 1
type 1
type 1
Future Of Gestion des exception
type 1
type 1
type 1
References:
- P.O.O. 2(Programmation Orientée Objet 2) - CHOUITI Sidi Mohammed - Cours pour 2ème année Ingénieurs - Département d’Informatique - Université de Tlemcen - 2023-2024
Created:: 2024-03-11 10:21