Une exception en programmation désigne une condition exceptionnelle survenant lors de l'exécution d'un programme. Elle est utilisée lorsque cette condition peut être mieux gérée ailleurs qu'à l'endroit où elle se produit. Voici quelques exemples :
Dans ces cas, l'exception doit être traitée en dehors de son point de génération pour corriger la cause sous-jacente.
L'image ci-dessous illustre la hiérarchie principale des exceptions Java. La classe de base est Throwable, sous-classée en Exception et Error. Exception concerne les conditions récupérables par l'application. Error signale des erreurs graves de l'environnement JVM, comme OutOfMemoryError ou StackOverflowError, que l'application ne doit pas intercepter.

Les exceptions se divisent en vérifiées (checked) et non vérifiées (unchecked). Une exception vérifiée doit être gérée par le code appelant ou déclarée ; le compilateur l'exige. Une non vérifiée (sous-classe de RuntimeException) peut propager librement.
La méthode suivante tente de créer un FileReader. Son constructeur lève FileNotFoundException (vérifiée), qui doit être gérée ou déclarée.
Ce code ne compile pas :
private void loadFile(String filename) {
FileReader in = new FileReader(filename);
}
Pour compiler, gérez-la :
private void loadFile(String filename) {
try {
FileReader in = new FileReader(filename);
} catch (FileNotFoundException ex) {
// Gérer l'exception ici
}
}
Ou déclarez-la :
private void loadFile(String filename) throws java.io.FileNotFoundException {
FileReader in = new FileReader(filename);
}
Une non vérifiée, sous-classe de RuntimeException, n'exige pas de gestion explicite. Exemple générant NullPointerException :
private void handleEvent() {
String name = null;
if (name.length() > 0) {
}
}
Pour simplifier, encapsulez une vérifiée dans une non vérifiée.
method_1() lève SQLException :
private void method_1() throws SQLException {
// ...
throw new SQLException();
}
Dans method_2() :
private void method_2() {
try {
method_1();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
La trace de pile liste les appels actifs capturés par la JVM, avec classe, méthode, fichier et ligne. Utile pour déboguer.
Exemple :
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 8, Size: 5
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at sample.sample1.main(sample1.java:24)
Utilisez try-catch pour corriger. L'objet exception fournit des infos via ses méthodes.
Exemple de logging :
private void loadConfig() {
try {
// Code pouvant lever IOException
} catch (IOException ex) {
log.warning(ex.getMessage());
}
}
Récupérer cause encapsulée :
Throwable cause = ex.getCause();
log.warning("Cause : " + cause.getMessage());
Trace de pile :
StringBuilder sbuf = new StringBuilder("Stack Trace:");
for (StackTraceElement el : ex.getStackTrace()) {
sbuf.append(el.getClassName() + "." + el.getMethodName()).append("\n");
}
log.warning(sbuf.toString());
Logger et relancer :
try {
// ...
} catch (IOException ex) {
log.warning(ex.getMessage());
throw ex;
}
Imprimer trace :
try {
// ...
} catch (IOException ex) {
PrintStream out = ...;
out.println(ex.getMessage());
ex.printStackTrace(out);
}
Multi-exceptions :
try {
// ...
} catch (IOException ex) {
// IO
} catch (SQLException ex) {
// SQL
}
Ou multi-catch (Java 7+) :
try {
// ...
} catch (IOException | SQLException ex) {
// Commun
} catch (SAXException ex) {
// SAX
}
Nettoyez les ressources (fichiers, connexions) dans finally :
InputStream in = null;
try {
in = new FileInputStream(filename);
// ...
} catch (IOException ex) {
log.warning(ex.getMessage());
} finally {
if (in != null) in.close();
}
Depuis Java 7, simplifie le nettoyage pour AutoCloseable :
try (InputStream in = new FileInputStream("..")) {
// Utilisation
}
Multi-ressources :
try (InputStream in = new FileInputStream("..");
Connection con = ...) {
// ...
}
Classe exemple :
public class MyClass implements AutoCloseable {
public void close() {
// Nettoyage
}
}
try (MyClass obj = new MyClass(..)) {
// ...
}
Les exceptions sont essentielles pour signaler et gérer les erreurs en Java. Une bonne utilisation améliore la robustesse du code en production.
Avez-vous des anecdotes sur les exceptions ? Partagez en commentaires !
Crédit image : Dmitry Nikolaev via Shutterstock.com
[]