Une exception dans la programmation signifie une condition exceptionnelle à un moment donné de l'exécution du programme. Il est utilisé lorsque la condition exceptionnelle peut être mieux gérée ailleurs plutôt que là où elle se produit. Prenons les exemples suivants :
Dans tous ces cas (et bien d'autres), l'exception doit être traitée en dehors de l'emplacement où elle est générée afin que la cause sous-jacente puisse être traitée.
L'image ci-dessous montre les principales parties de la hiérarchie des exceptions Java. La classe de base est Throwable qui est sous-classé dans Exception et Erreur . Classe Exception est pour les conditions liées au programme que les applications peuvent détecter dans une tentative de sauver la situation. Classe Erreur , d'autre part, sert à indiquer les erreurs graves dans l'environnement d'exécution Java que les applications ne doivent pas intercepter. Voici quelques exemples :OutOfMemoryError et StackOverflowError .
Une exception encore une fois est de deux types :cochée et non cochée. Une exception vérifiée doit être gérée par le code appelant. Cette règle est appliquée par le compilateur Java. Une exception non vérifiée, en revanche, peut être propagée dans la chaîne d'appel sans avoir à la déclarer explicitement. Les exemples ci-dessous clarifieront.
La méthode suivante tente de créer FileReader à partir d'un dossier. Le constructeur lève une exception vérifiée FileNotFoundException qui doit être gérée par le code appelant ou déclarée comme levée.
Le code suivant ne sera pas compiler puisqu'il ne fait ni l'un ni l'autre.
private void loadFile(String filename)
{
FileReader in =new FileReader(filename);
}
Une façon d'obtenir le code à compiler est de gérer l'exception (voir ci-dessous).
private void loadFile(String filename)
{
essayer {
FileReader in =new FileReader(filename)); {
} catch(FileNotFoundException ex) {
// gérer l'exception ici
}
}
Si l'exception ne peut pas être gérée directement par l'appelant, elle doit être déclarée dans la signature de la méthode.
private void loadFile(String filename) lance java.io.FileNotFoundException
{
FileReader in =new FileReader(filename)); {
}
Une exception non contrôlée est une sous-classe de RuntimeException et n'ont pas besoin d'être manipulés directement ou déclarés comme ci-dessus. Par exemple, le code suivant génère une NullPointerException , qui est un type de RuntimeException . Le code se compile cependant sans erreur depuis NullPointerException est une exception non contrôlée.
handleEvent vide privé()
{
Nom de chaîne =null ;
si ( nom.longueur()> 0 ) {
}
}
Compte tenu de la discussion ci-dessus sur les exceptions cochées et non cochées, il semble qu'il est plus facile de traiter les exceptions non cochées puisque vous n'avez pas à les déclarer ou à les gérer vous-même. Avec cette commodité à l'esprit, il peut parfois être utile d'envelopper une exception cochée dans une exception non cochée.
L'exemple de code suivant montre comment encapsuler une exception. La méthode method_1() lance une SQLException dans son corps. Pour que le code se compile correctement, l'exception doit être déclarée levée.
méthode vide privée_1() lève SQLException {
...
lancer une nouvelle exception SQL ;
}
Lorsque cette méthode est invoquée depuis une autre méthode (method_2() ), cette méthode peut intercepter l'SQLException et encapsulez-le dans une exception non vérifiée, afin qu'il n'ait pas à déclarer l'exception dans sa signature de méthode.
méthode vide privée_2() {
essayer {
method_1();
} catch(java.sql.SQLException ex) {
lancer une nouvelle RuntimeException(ex);
}
}
Une trace de pile d'exception fait référence au tableau de cadres de pile actifs, chacun représentant un appel de méthode, capturé par la JVM au moment où l'exception a été levée. Chaque cadre de pile inclut l'emplacement de l'invocation de la méthode, y compris le nom de la classe, le nom de la méthode et éventuellement le nom du fichier source Java et le numéro de ligne dans le fichier. Il est utile pour retracer la séquence d'appels à l'origine de l'erreur.
Voici une trace de pile typique, obtenue à partir de l'objet exception lorsqu'il a été intercepté.
Exception dans le thread "main" java.lang.IndexOutOfBoundsException :Index :8, Taille :5
à java.util.ArrayList.rangeCheck(ArrayList.java:653)
à java.util.ArrayList.get(ArrayList.java:429)
à sample.sample1.main(sample1.java:24)
L'exception détectée ici est IndexOutOfBoundsException . Il contient des informations supplémentaires sur l'erreur. La trace de pile contient 3 cadres de pile, dont chacun inclut les informations d'emplacement comme indiqué.
Une exception peut être gérée en l'attrapant dans un try-catch bloquer et prendre les mesures correctives nécessaires. L'exception L'objet fournit plusieurs méthodes pour extraire des informations sur la condition qui l'a provoqué.
Le code suivant consigne le message d'erreur dans un fichier journal.
private void loadConfig() {
essayer {
// appelle le code qui pourrait générer une IOException
} catch(java.io.IOException ex) {
// gérer l'exception ici. Peut être enregistré dans un fichier journal.
log.warning(ex.getMessage());
}
}
Lorsqu'une exception est encapsulée dans une autre, vous pouvez récupérer l'exception encapsulée :
Cause jetable =ex.getCause();
log.warning("Cause sous-jacente :" + cause.getMessage());
Avez-vous besoin d'accéder à la trace de la pile, et peut-être d'extraire le nom de la méthode qui l'a provoqué ?
StringBuilder sbuf =new StringBuilder("Stack Trace:");
pour (StackTraceElement el :ex.getStackTrace()) {
sbuf.append(el.getClassName() + "." + el.getMethodName()).append("
");
}
log.warning(sbuf.toString());
Ou peut-être consigner l'exception et la relancer ?
essayez {
...
} catch(java.io.IOException ex) {
log.warning(ex.getMessage());
jeter ex;
}
L'exception la classe fournit un printStackTrace() méthode qui peut imprimer la trace de la pile sur votre propre PrintStream (ou PrintWriter ).
essayez {
...
} catch(java.io.IOException ex) {
PrintStream out =...;
out.println(ex.getMessage());
ex.printStackTrace(out);
}
Vous pouvez intercepter plusieurs types d'exceptions en un seul essai bloquer et effectuer une gestion spécifique pour chaque type d'exception.
essayez {
// lève quelques exceptions ici
} catch(java.io.IOException ex) {
// Gestion spécifique des IOExceptions ici
} catch(java.sql.SQLException ex) {
// Traitement spécifique de SQLException ici
}
Pour intercepter plusieurs types d'exceptions mais utiliser le même code de gestion, vous pouvez déclarer un catch bloc avec plusieurs types comme suit :
essayez {
// lève quelques exceptions ici
} catch(java.io.IOException | java.sql.SQLException ex) {
// Traitement spécifique des exceptions IOException et SQLException ici
} catch(SAXException ex) {
// Gestion spécifique de SAXException ici
}
Lorsqu'il s'agit de code pouvant générer des exceptions, il est essentiel d'effectuer un nettoyage approprié de toutes les ressources, telles que les fichiers ouverts, les connexions à la base de données, etc. Le nettoyage des ressources doit être effectué enfin bloquer. De cette façon, la sortie normale et la sortie exceptionnelle d'un bloc invoquent le code de nettoyage.
InputStream in =null ;
essayer {
...
in =new FileInputStream(nom de fichier);
...
} catch(java.io.IOException ex) {
log.warning(ex.getMessage());
} finalement {
// le code ici est exécuté à la sortie du bloc try,
// que ce soit normalement ou à cause d'une exception
if ( in !=null ) in.close();
}
Java 1.7 a introduit le try-with-resources construction qui facilite le nettoyage des ressources. Il ressemble à ceci :
try( InputStream in =new FileInputStream(..) ) {
// code qui utilise InputStream.
}
Lorsque le code sort du bloc (que ce soit proprement ou à cause d'une exception), le InputStream variable est automatiquement nettoyée.
Nettoyez plusieurs ressources en les déclarant toutes dans l'en-tête du bloc.
try( InputStream in =new FileInputStream(..);
Connexion con =... ; ) {
// code qui utilise InputStream et Connection.
}
Tout objet dont la classe implémente le AutoCloseable l'interface peut être nettoyée de cette manière. La classe suivante effectue un nettoyage spécifique dans close() méthode.
la classe publique MyClass implémente AutoCloseable {
public vide fermer() {
// code de nettoyage ici
}
}
Utiliser une instance de cette classe dans un try-with-resources bloquer.
try( MaClass obj =new MaClass(..) ) {
// code qui utilise l'objet MyClass.
}
Examinons maintenant quelques exceptions couramment rencontrées.
Les exceptions sont la principale méthode de signalement et de gestion des erreurs en Java. L'utilisation appropriée des exceptions améliore la qualité du code et aide à résoudre les problèmes en production.
Avez-vous des histoires de guerre liées à des exceptions à raconter ? Si oui, parlez-nous-en dans la section des commentaires ci-dessous.
Crédit image :Dmitry Nikolaev via Shutterstock.com