rakesh99
rakesh99

Reputation: 1266

Catch exceptions which are not thrown locally?

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

Answers (1)

yshavit
yshavit

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 or Exception or a superclass of Exception, 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 of C'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 of C's parameter is the same as or a subclass of the type of A'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:

  • An unchecked exception
  • Exception
  • Throwable (which is the only superclass of Exception other than Object, which you can't catch)
  • a checked exception that the try block can throw

The 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

Related Questions