Reputation: 1266
My question is related to syntactic behavior of the try catch block
Empty try block with a catch as this
void fun() {
try {}
catch(Exception e) {}
}
or
try {}
catch(ArrayIndexOutOfBoundsException e) {}
compiles well but the compiler complains with
try {}
catch(IOException e) {}
Why does the compiler allow catching anything that is of type Exception or RuntimeException whereas it complains for unreachable code with checked exceptions? Is it because the JVM code can throw those types? How could the JVM possibly throw ArrayIndexOutOfBoundsException in an empty try block?
Upvotes: 9
Views: 3083
Reputation: 43391
The empty block is a special case which isn't specially handled by the JLS. What the JLS does require is that if you catch a checked exception, the code in the try
block must have been able to throw that exception (that is, it threw it directly or called a method that was declared to possibly throw it).
In other words, there's a sanity check specifically for checked exceptions, but not for all exceptions with checked exceptions getting extra consideration.
This is described in JLS 14.21, and specifically:
It is a compile-time error if a statement cannot be executed because it is unreachable.
...
A catch block
C
is reachable iff both of the following are true:
Either the type of
C
's parameter is an unchecked exception type orException
or a superclass ofException
, or some expression or throw statement in the try block is reachable and can throw a checked exception whose type is assignable to the type ofC
's parameter. (An expression is reachable iff the innermost statement containing it is reachable.)See §15.6 for normal and abrupt completion of expressions.
There is no earlier catch block
A
in the try statement such that the type ofC
's parameter is the same as or a subclass of the type ofA
's parameter.
Emphasis added: it shows that if you're catching an unchecked exception type, the catch block is reachable.
I personally find the wording a bit confusing. Slightly reworded, the first bullet point just says that the catch clause must catch one of:
Exception
Throwable
(which is the only superclass of Exception
other than Object
, which you can't catch)try
block can throwThe second bullet guards against a catch
block being unreachable because of a previous catch
in that try
. For instance:
try {
whatever();
} catch (Exception e) {
handleException(e);
} catch (NullPointerException e) {
// This block is unreachable, because a NullPointerException is an
// Exception and will thus be handled by the previous catch block.
handleNpe(e);
}
Upvotes: 11