Catch exceptions which are not thrown locally?

倖福魔咒の 提交于 2020-01-02 02:26:08

问题


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?


回答1:


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);
}


来源:https://stackoverflow.com/questions/23817401/catch-exceptions-which-are-not-thrown-locally

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!