Ch. 4 — Exceptions et manipulation du système
La hiérarchie Throwable de bout en bout : checked et unchecked, ordre des catch, propagation, exceptions personnalisées, try-with-resources, multi-catch — puis la classe File pour dialoguer avec le système.
Un mécanisme intégré au langage
La gestion des erreurs Java repose sur des objets Exception et Error, et sur des
instructions pour les détecter, capturer et traiter (try, catch, finally) comme pour
les lever ou les propager (throw, throws). Quand une erreur survient, un objet
spécifique est créé — on dit que l'exception est levée — puis propagé à travers la
pile d'exécution jusqu'à ce qu'il soit traité. Objectif : renforcer la sécurité et la
robustesse du code.
int i = 3;
int j = 0;
System.out.println("Result = " + (i / j));
// → java.lang.ArithmeticException: / by zero, avec la trace des appelsLa hiérarchie Throwable
Throwable, fille directe d'Object, est la classe mère de toutes les exceptions et
erreurs : seules ses instances — ou celles de ses classes dérivées — peuvent être levées et
capturées. Elle se scinde en deux branches :
Error: erreur grave dans la machine virtuelle — l'application s'arrête instantanément, ces erreurs n'ont pas vocation à être traitées (VirtualMachineError,OutOfMemoryError,StackOverflowError,LinkageError…). 12 classes en dérivent directement, car non traitables ;Exception: les erreurs moins graves, que l'application peut traiter — obligatoirement pour les checked (IOException,ClassNotFoundException…), optionnellement pour les unchecked, c'est-à-dire lesRuntimeException(NullPointerException,ArithmeticException,ClassCastException…). 75 classes en dérivent directement, dont 31 sousIOExceptionet 53 sousRuntimeException.
try, catch, finally
try surveille un bloc susceptible de lever une exception ; catch la capture et la
traite. Les blocs catch sont parcourus en séquence, et le premier compatible — par
polymorphisme d'héritage — traite l'exception. Le bloc finally, s'il existe, est
toujours exécuté : après toutes les instructions du try, ou après la dernière
instruction qui a traité une exception levée. Dès qu'une exception survient, le reste du
bloc est abandonné : si riskyMethod1() lève, riskyMethod2() n'est pas exécutée.
Le traitement peut être informatif — afficher ou exporter un message facilitant
l'identification de l'erreur — ou curatif — corriger : valeur par défaut, paramètre
modifié, méthode différente. Un catch vide ignore l'exception : mauvaise pratique, à
éviter.
L'ordre des catch
S'il y a plusieurs types à intercepter, il faut autant de blocs catch — et leur ordre
n'est pas décoratif : du spécifique au générique, sous peine d'erreur de compilation :
try {
System.out.println("résultat = " + (i / j));
} catch (Exception e) { // capture déjà tout…
} catch (ArithmeticException ae) { // …donc inatteignable : ne compile pas
}Lever et propager
throw lève manuellement une exception : throw new MyException();. La clause
throws figure dans la signature : elle déclare qu'une méthode peut lever une
exception sans la traiter. Toute méthode appelante doit alors choisir : traiter
(bloc try/catch) ou propager à son tour. Les Error et RuntimeException n'ont à
être ni déclarées ni propagées.
Règle du cours : une méthode qui lève une exception ne traite pas celles levées par les
méthodes qu'elle appelle — elle liste les siennes via throws, quitte à concentrer le
traitement dans une méthode qui en gère plusieurs. But : éviter la dilution du
traitement des cas problématiques dans le code.
Throwable et exceptions personnalisées
Throwable offre des constructeurs — sans message, avec String message, avec message
et cause — et des méthodes à connaître : getMessage(), toString(),
printStackTrace(), getCause(), initCause(). Pour la division par zéro :
getMessage() renvoie / by zero, toString() renvoie
java.lang.ArithmeticException: / by zero, printStackTrace() ajoute la trace des appels.
Créer sa propre exception se fait par héritage — de Exception (checked) ou de
RuntimeException (unchecked), jamais d'Error — avec, par convention, le mot
« Exception » dans le nom :
public class WrongInputException extends Exception {
public WrongInputException() { super(); }
public WrongInputException(String message) { super(message); }
}Dérivée d'une unchecked, c'est plus facile — rien à déclarer — mais risqué : on peut oublier de la traiter, ou ne pas savoir qu'une méthode peut la lever. Le cours recommande le checked.
try-with-resources et multi-catch
Le try-with-resources est lié à l'interface AutoCloseable, qui garantit une méthode
close() de fermeture de ressource — l'utiliser sur un type qui ne l'implémente pas ne
compile pas. Les ressources se placent entre parenthèses juste après try (séparées par
des ; si plusieurs) ; le bloc peut exister sans catch ni finally ; depuis Java
SE 9, la variable peut être déclarée hors du bloc. La version classique du cours —
BufferedReader créé hors du try — souffre de deux maux : ressources non fermées en cas
d'exception, return final vide de sens. Le try-with-resources règle les deux :
static String readingOneLineWithResources(String chemin) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(chemin))) {
return br.readLine();
} // close() invoquée automatiquement
}Le multi-catch attrape plusieurs types avec un seul bloc — plus précis que la capture
par polymorphisme : catch (InterestingException | SpecificException e). Contrepartie :
sur e, seuls les membres du premier ancêtre commun aux types attrapés sont
utilisables (Exception la plupart du temps).
Dialoguer avec le système : la classe File
Un programme échange des informations hétérogènes (texte, image, son) avec des sources et
destinations variées — fichiers, sockets réseau, autres programmes. Deux aspects : les
traitements du système (créer/supprimer des fichiers, explorer l'arborescence → la
classe File) et les flux d'informations (lire un fichier, écrire sur une socket →
les classes Reader et InputStream, qui encapsulent l'envoi et la réception).
Portabilité d'abord : les chemins diffèrent d'un OS à l'autre. File.separator construit
un chemin (tmp/debug.log sous Unix), System.getProperty("user.dir") donne le répertoire
courant. Les méthodes de File se regroupent par intention :
- tester :
isFile(),isDirectory(),exists(),canRead(),canWrite(),canExecute(),isHidden(),length(),lastModified()/setLastModified(); - droits :
setReadable(),setWritable(),setExecutable(); - créer/supprimer :
createNewFile()(sinonfalse, ouIOExceptionen cas d'erreur),delete()(falsesi impossible),mkdir()/mkdirs()(répertoires imbriqués),deleteOnExit()(effacement à la fin de l'application) ; - chemins :
getName(),getParent(),getPath(),getAbsolutePath(),getCanonicalPath()(chemin direct, résout..et liens symboliques — peut leverIOException) ; - explorer :
list()/listFiles()retournent le contenu d'un répertoire — enString[]ouFile[], ordre imprédictible — filtrables parFileFilter/FilenameFilter; la méthode statiquelistRoots()retourne les racines du système de fichiers.
A retenir
Throwable→Error(JVM, non traitable) etException(traitable, saufRuntimeExceptionfacultative) ;- catch du spécifique au générique ;
finallytoujours exécuté ; jamais de catch vide ; throwlève,throwsdéclare ; propager plutôt que diluer le traitement ;- exceptions personnalisées :
extends Exception, nom en « …Exception » ; AutoCloseable+ try-with-resources ;Filepour le système,Reader/InputStreampour les flux.
Une ArithmeticException est une Exception par polymorphisme d'héritage :
l'exception levée valide toujours le premier bloc, le second devient inatteignable, le
compilateur refuse.
throw new MyException(); lève une exception, dans le corps d'une méthode.
throws MyException déclare dans la signature que la méthode peut la lever sans la
traiter — les appelants devront la traiter ou la propager.
coursQU_04.pdf
R2.03 · Cours 4 — Gestion des exceptions / manipulation du système · 38 diapositives
Chargement du document…
Dernière mise à jour le
Ch. 3 — Qualité logicielle, Git avancé
Métriques de qualité (Déméter, complexité cyclomatique, Halstead), dette technique, SOLID, TDD, SCRUM et XP, PMD — puis Git avancé : tags, branches, merge, rebase et conflits.
Ch. 5 — Introduction aux patrons de conception
Pourquoi le design se dégrade et quels principes le protègent — puis les patrons de conception : familles GoF et trois patrons en profondeur, Singleton (5 implémentations), Facade et Factory.