Catching multiple exceptions in Java-8
While trying out the multi-catch feature I found in my m1()
method everything is working fine as expected.
However, in m2()
the same code does not compile. I have just changed the syntax to reduce the number of lines of 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 {
}
}
Why doesn't method m2()
compile?
The type of the expression
b ? new Excep1() : new Excep2()
is Exception
, since that's the common supertype of Excep1
and Excep2
.
However, you are not catching Exception
, so the compiler complains about it.
If you catch Exception
, it will pass compilation:
public int m2(boolean b) {
try {
throw b ? new Excep1() : new Excep2();
} catch (Exception e) {
return 0;
}
}
I tried to find the JLS entry that explains the type of conditional ternary expression in your example.
All I could find was that this particular expression is a 15.25.3. Reference Conditional Expression.
I'm not entirely sure if it counts as a poly expression or a standalone expression. I think it's standalone (since poly expressions involve an assignment context or an invocation context, and I don't think a throw
statement counts as either of those).
For a standalone expression: "If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression."
In your case, the second and third operands have three common types - Object
, Throwable
and Exception
- the type of the expression must be one of the latter two, since, "The Expression in a throw statement must either denote a variable or value of a reference type which is assignable (§5.2) to the type Throwable."
It appears that the compiler picks the most specific common type (Exception
), and therefore a catch (Exception e)
solves the compilation error.
I also tried to replace your two custom exceptions with two sub-classes of IOException
, in which case catch (IOException e)
solves the compilation error.
You're confusing the compiler with this line:
throw b ? new Excep1() : new Excep2();
The compiler sees that the result of the expression (to the right of the throw) is the common super class between Except1 and Except2, which is Exception, and therefore the effective type you are throwing becomes Exception. The catch statement cannot pick up that you're trying to throw Excep1 or Except2.