En essayant la fonction multi-catch que j'ai trouvée dans ma m1()
méthode, tout fonctionne bien comme prévu.
Cependant, dans m2()
le même code ne compile pas. Je viens de changer 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()
compile- t-elle pas ?
Réponses:
Le type de l'expression
est
Exception
, puisque c'est le supertype commun deExcep1
etExcep2
.Cependant, vous n'attrapez pas
Exception
, donc le compilateur s'en plaint.Si vous attrapez
Exception
, il passera la compilation: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 un 15.25.3. Expression conditionnelle de référence .
Je ne suis pas tout à fait sûr si cela compte comme une expression poly ou une expression autonome. Je pense que c'est autonome (puisque les expressions poly impliquent un contexte d'affectation ou un contexte d'invocation, et je ne pense pas qu'une
throw
déclaration compte pour 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
etException
- le type de l'expression doit être l'un des deux derniers, car "l'expression dans une instruction throw doit soit désigner une variable soit une valeur d'un type de référence qui est assignable (§5.2) au type Throwable. "Il semble que le compilateur sélectionne le type commun le plus spécifique (
Exception
), et donccatch (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
, auquel cas celacatch (IOException e)
résout l'erreur de compilation.la source
Excep1
ouExcep2
. Cela ne peut être queException
.Vous confondez le compilateur avec cette ligne:
Le compilateur voit que le résultat de l'expression (à gauche du lancer) 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.
la source
Java vous restreint pour intercepter ou déclarer tous les types d'exceptions que la méthode peut lancer,
Il recherche pour parent commun pour les deux (/) toutes les exceptions et vous vous attendez à attraper ou Déclarons ce qui jette, par exemple , si
Excep1
étendThrowable
vous devrez attraper aussi ThrowableDans le premier cas, Java est sûr que vous lancez
Excep1
ouExcep2
la source