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 :
  • 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 .

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.

Permalink  |  Commentaires (0)


Comments:

Post a Comment:
  • HTML Syntax: Allowed