我的问题与 try catch 块的语法行为有关
带有 catch 的空 try 块,如下所示
void fun() {
try {}
catch(Exception e) {}
}
or
try {}
catch(ArrayIndexOutOfBoundsException e) {}
编译良好,但编译器抱怨
try {}
catch(IOException e) {}
为什么编译器允许捕获 Exception 或 RuntimeException 类型的任何内容,而它却抱怨带有已检查异常的无法访问的代码?是因为 JVM 代码可以抛出这些类型吗? JVM 怎么可能在空的 try 块中抛出 ArrayIndexOutOfBoundsException?
空块是一种特殊情况,JLS 不会专门处理。什么是JLSdoes要求是如果你捕获了一个已检查的异常,则代码中try
block 必须能够抛出该异常(也就是说,它直接抛出该异常或调用声明为可能抛出该异常的方法)。
换句话说,有专门针对已检查异常的健全性检查,但不适用于all带有已检查异常的异常得到额外考虑。
这在JLS 14.21 http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21,具体来说:
如果某个语句由于无法访问而无法执行,则这是一个编译时错误。
...
一个 catch 块C
是可到达的,当且仅当满足以下两个条件:
-
要么是类型C
的参数是未经检查的异常类型 or Exception
或一个超类Exception
,或者 try 块中的某些表达式或 throw 语句是可达的,并且可以抛出一个已检查异常,其类型可分配给C
的参数。 (表达式是可达的,当且仅当包含它的最里面的语句是可达的。)
有关表达式的正常完成和突然完成,请参阅第 15.6 节。
没有更早的 catch 块A
在 try 语句中,这样的类型C
的参数与 的类型相同或者是该类型的子类A
的参数。
添加了重点:它表明如果您捕获未经检查的异常类型,则可以访问 catch 块。
我个人觉得这个措辞有点混乱。稍微改写一下,第一个要点只是说 catch 子句必须捕获以下之一:
- 未经检查的异常
Exception
-
Throwable
(这是唯一的超类Exception
以外Object
,你无法捕捉到)
- 一个已检查的异常
try
块可以扔
第二颗子弹可以防止catch
由于先前的块而无法访问catch
在那里面try
。例如:
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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)