70 votes

Capture d'exceptions multiples en Java-8

En essayant le multi-catch que j'ai trouvé dans mon m1() méthode tout fonctionne bien comme prévu.

Cependant, en m2() le même code ne compile pas. J'ai juste changé la syntaxe pour réduire le nombre de lignes de code.

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

Pourquoi la méthode ne m2() compiler ?

82voto

Eran Points 35360

Le type de l'expression

b ? new Excep1() : new Excep2()

est Exception puisque c'est le supertype commun de Excep1 y Excep2 .

Cependant, vous n'attrapez pas Exception et le compilateur s'en plaint.

Si vous attrapez Exception il passera la compilation :

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

J'ai essayé de trouver l'entrée JLS qui explique le type d'expression ternaire conditionnelle dans votre exemple.

Tout ce que j'ai pu trouver, c'est que cette expression particulière est une 15.25.3. Expression conditionnelle de référence .

Je ne sais pas vraiment si cela compte comme une expression poly ou une expression autonome. Je pense qu'il s'agit d'une expression autonome (puisque les poly-expressions impliquent un contexte d'affectation ou un contexte d'invocation, et je ne pense pas qu'une expression de type throw compte comme l'un ou l'autre).

Pour une expression autonome : "Si les deuxième et troisième opérandes ont le même type (qui peut être le type nul), alors c'est le type de l'expression conditionnelle."

Dans votre cas, les deuxième et troisième opérandes ont trois types communs - Object , Throwable y Exception - le type de l'expression doit être l'un des deux derniers, puisque "L'expression dans une instruction throw doit soit dénoter une variable ou une valeur d'un type de référence qui est assignable (§5.2) au type Throwable".

Il semble que le compilateur choisisse le type commun le plus spécifique ( Exception ), et donc une catch (Exception e) résout l'erreur de compilation.

J'ai également essayé de remplacer vos deux exceptions personnalisées par deux sous-classes de IOException dans ce cas catch (IOException e) résout l'erreur de compilation.

23voto

GideonleGrange Points 346

Vous troublez le compilateur avec cette ligne :

throw b ? new Excep1() : new Excep2();

Le compilateur voit que le résultat de l'expression (à droite du throw) est la super classe commune entre Except1 et Except2, qui est Exception, et donc le type effectif que vous lancez devient Exception. L'instruction catch ne peut pas détecter que vous essayez de lancer Excep1 ou Except2.

4voto

user7294900 Points 16410

Java vous limite à attraper ou à déclarer tous les types d'exceptions que les méthodes peuvent lancer,

Il recherche le parent commun pour les deux (/tous) exceptions et s'attend à ce que vous les attrapiez ou les déclariez comme des lancers, par exemple si Excep1 étend Throwable vous devrez également attraper un Throwable

Dans le premier cas, Java est sûr que vous êtes soit en train de lancer Excep1 o Excep2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X