为什么在Java中,Exception即使没有抛出异常,我们也可以捕获它,但是却不能捕获它的子类(“ unchecked” RuntimeException及其子类除外)。示例代码:
Exception
RuntimeException
class Test { public static void main(String[] args) { try { // do nothing } catch (Exception e) { // OK } try { // do nothing } catch (IOException e) { // COMPILER ERROR: Unreachable catch block for IOException. //This exception is never thrown from the try statement body } } }
有任何想法吗?
任何 代码RuntimeException都可以引发A。换句话说,编译器无法轻松预测可以抛出哪种代码。阿可通过捕获块。 __RuntimeException``catch(Exception e)
RuntimeException``catch(Exception e)
IOException但是,这是一个检查的异常- 只有声明为抛出该异常的方法调用才可以这样做。编译器可以(合理地)确信除非有声明将其抛出的方法调用,否则它不可能发生。
IOException
Java编译器根本不考虑“有没有代码在所有try块内”的局面-它总是让你赶上unchecked异常,在所有 合理的 情况下会出现代码, 可以 潜在地抛出一个未经检查的异常。
从JLS的14.21节开始:
如果满足以下两个条件,则可以到达catch块C: try块中的某些表达式或throw语句是可到达的,并且可以引发类型可以分配给catch子句C的参数的异常。 在try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或属于其子类。
如果满足以下两个条件,则可以到达catch块C:
可以说,编译器应该意识到在您的第一种情况下,try块中 没有 表达式……对我来说,这似乎仍然是一个无法到达的catch子句。
编辑:如注释中所述,第14.20节包含以下内容:
如果catch子句捕获了已检查的异常类型 E1, 但是不存在已检查的异常类型 E2 ,则以下所有条件均成立,这是编译时错误: E2 <: E1 try与该catch子句对应的块可以抛出 E2 前面没有catch立即封闭try语句块捕获 E2 或的超 E2 。 除非 E1 是Exception类。
如果catch子句捕获了已检查的异常类型 E1, 但是不存在已检查的异常类型 E2 ,则以下所有条件均成立,这是编译时错误:
catch
try
除非 E1 是Exception类。
因此,这似乎是您 实际上 在犯规的内容,但是对于14.21中无法到达的捕获块而言,此规范并不明确。