Java 7 : Meilleure gestion des exceptions
Une nouvelle proposition pour Java 7 est à l'ordre du jour : l'amélioration de la gestion des exceptions.
Cette amélioration consisterait en deux parties :
Un tel code est entièrement valide, mais contraignant. En effet, essayons de l'encapsuler dans une méthode :
J'ai été obligé de rajouter un magnifique
Des techniques pour palier à ce problème sont assez répandues, comme par exemple l'encapsulation de l'exception levée dans une
L'amélioration dans ce cas là consisterais à pouvoir attraper les exceptions en les marquant
Attraper plusieurs types d'exceptions dans un bloc
Un simple petit exemple devrait clarifier la situation sur cette nouvelle fonctionnalité :
Pour récupérer deux exceptions (
Dans cet exemple, le bloc
Une autre syntaxe a été proposée, cette fois-ci basée sur les generics :
Le débat tourne autour de la justification des exceptions vérifiées en Java. Est-ce que les exceptions vérifiées sont utiles, où alors devraient elles être toutes remplacées par des exceptions non vérifiées ?
Pour rappel, une exception vérifiée est une exception qui doit obligatoirement être soit déclarée (via
Je dois avouer que je suis plutôt du coté des "défenseurs" des exceptions vérifiées, même si elles sont assez contraignantes à mettre en place dans certaines situation, notamment pour l'introduction des closures.
Cette amélioration consisterait en deux parties :
- Une amélioration pour relever les exception attrapées.
- La possibilité d'attraper plusieurs types d'exceptions dans un seul bloc
catch
Relever une exception déjà attrapée
Lors de la rédaction de libraires en Java, il arrive couramment d'avoir à attraper une exception, d'effectuer certains traitements, certains enregistrements dans des fichiers de log, puis de vouloir la relancer derrière. Un petit exemple (inspiré de la proposition originale) :try { throw new MyException(); } catch (Throwable t) { // Log the exception throw t; }
Un tel code est entièrement valide, mais contraignant. En effet, essayons de l'encapsuler dans une méthode :
public void doSomeStuff() throws Throwable { try { throw new MyException(); } catch (Throwable t) { // Log the exception throw t; } }
J'ai été obligé de rajouter un magnifique
throws Throwable. Pourquoi ? Tout simplement parce que la ligne throw t; lève une exception, de type Throwable. Le compilateur impose donc de déclarer Throwable dans le prototype de la méthode. Et ce, même si le bloc try ne lève que des exceptions de type MyException, dans notre exemple.Des techniques pour palier à ce problème sont assez répandues, comme par exemple l'encapsulation de l'exception levée dans une
RuntimeException. Mais on perd tout le bénéfice des exceptions vérifiées.L'amélioration dans ce cas là consisterais à pouvoir attraper les exceptions en les marquant
final. L'exception marquée final ne pouvant changer, le compilateur est certain que la ligne throw t; ne lèvera qu'une exception levée dans le bloc try. Dans notre cas, une exception de type MyException. L'exception MyException serait donc la seule à déclarer. Et ce code deviendrait complètement valide :
public void doSomeStuff() throws MyException { try { throw new MyException(); } catch (final Throwable t) { // Log the exception throw t; } }
Attraper plusieurs types d'exceptions dans un bloc catch
Un simple petit exemple devrait clarifier la situation sur cette nouvelle fonctionnalité :
try { klass.newInstance(); } catch (InstantiationException ex) { ex.printStackTrace(System.err); } catch (IllegalAccessException ex) { ex.printStackTrace(System.err); }
Pour récupérer deux exceptions (
InstantiationException et IllegalAccessException), deux blocs catch sont obligatoires. Même si le même traitement est effectué à l'intérieur. Dans notre cas, l'amélioration consisterais à permettre au développeur d'attraper deux types d'exceptions dans un seul bloc catch (inspiré de la proposition originale) :
try { klass.newInstance(); } catch (InstantiationException | IllegalAccessException ex) { ex.printStackTrace(System.err); }
Dans cet exemple, le bloc
catch est capable d'attraper les exception de type InstantiationException et celles de type IllegalAccessException.Une autre syntaxe a été proposée, cette fois-ci basée sur les generics :
try { // Some code... } <T extends MyException> catch (T t) { // Catch here... }
Une évolution plus radicale
Une autre évolution concernant les exceptions est débattue par les utilisateurs de Java ici et là.Le débat tourne autour de la justification des exceptions vérifiées en Java. Est-ce que les exceptions vérifiées sont utiles, où alors devraient elles être toutes remplacées par des exceptions non vérifiées ?
Pour rappel, une exception vérifiée est une exception qui doit obligatoirement être soit déclarée (via
throws), soit être attrapée (via catch).Je dois avouer que je suis plutôt du coté des "défenseurs" des exceptions vérifiées, même si elles sont assez contraignantes à mettre en place dans certaines situation, notamment pour l'introduction des closures.