如果我使用多个catch块,为什么java没有检测到不可到达的catch块?
研究方法如下:如果我使用多个catch块,为什么java没有检测到不可到达的catch块?,java,exception,try-catch,unreachable-code,Java,Exception,Try Catch,Unreachable Code,研究方法如下: static private void foo() { try { throw new FileNotFoundException(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace();
static private void foo() {
try {
throw new FileNotFoundException();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
尽管最后一个catch块实际上不可访问,但这段代码编译得很好
现在让comment抛出新的FileNotFoundException()代码>行
执行:
哎呀!我们看到
Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body
奇怪。为什么java在这些情况下使用双重标准
@Peter Rader的更新
与构造函数调用一起工作
更新
我注意到,在不同版本的java编译器上,我看到编译这段代码的不同结果
public class RethowTest {
public static void main(String[] args) {
try {
throw new FileNotFoundException();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
throw e;
}
}
}
在我的本地pc上:
java 1.7.0_45-
C:\Program Files\Java\jdk1.7.0_45\bin>javac D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java
D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java:15: warning: unreachable catch clause
} catch (IOException e) {
^
thrown type FileNotFoundException has already been caught
1 warning
java 1.6.0_38
D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java:16: unreported exception java.io.IOException; must be caught or declared to be thrown
throw e;
^
1 error
(JavaC1.7.0_09)-
如果实例化newfilenotfoundexception()
则调用类的构造函数FileNotFoundException
。在这个构造函数中,IOException理论上可以通过调用本机方法fillInStackTrace
抛出-编译器可能不知道构造函数的内容,可能会抛出IOException
参见本文:在示例中
如果编译器每次都检查构造函数FileNotFoundException()
:这是java忽略性能的开销。可访问性规则在java 8(和java 7)中定义如下:
当以下两项均为真时,可到达捕捉块C:
- C参数的类型要么是未检查的异常类型,要么是异常或异常的超类,或者try块中的某个表达式或throw语句是可访问的,并且可以抛出类型可分配给C参数类型的已检查异常。(如果包含表达式的最内层语句是可访问的,则表达式是可访问的。)
有关表达式的正常和突然完成,请参见§15.6
- try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或是A的参数类型的子类
请注意,这些规则并不禁止您的示例代码。第二个catch块不符合第二个要点的条件
(在示例的原始版本中,您捕获了异常
。可达性推理可能不同,但答案是相同的-有效代码。)
这是不一致的吗?以你为例,你可以说是这样的
为什么他们不在可达性规则中解决这个问题?我不知道。你需要问问Java设计者!!但是:
- 为了处理这个问题,可达性规则的制定需要更加复杂。规范中额外的(不必要的)复杂性是一个问题
- 你可能会说这种不一致性并没有破坏任何东西。可达性规则实际上只是一种在用户代码中发现潜在错误的方法。它不涉及类型安全或可预测的执行,即“破坏”Java运行时语义的东西
- 如果他们现在修改了规范,那将使一小部分有效的和正常工作的Java程序无效。考虑到稳定性是Java的主要卖点之一,这不是一个好主意
另一方面,我想不出一个技术原因来解释为什么他们不能在规范中解决这个“不一致性”
您注意到,一些Java编译器在第2次捕获时会发出警告消息。这没关系。Java编译器可以对(技术上)合法的Java代码发出警告
如果它们是错误,从技术上讲,这将是一个编译器错误…根据我对JLS的阅读。捕获(异常…
块将捕获运行时异常。原则上,它永远不会无法访问
FileNotFoundException
是一个选中的异常。只有当try块中的某个对象抛出它或它的某个子类时,才能访问它的catch块
[在响应请求时]异常包括运行时异常。原则上,它从来都不是不可访问的。只有当try块中的某个对象抛出FileNotFoundException或其基类时,才能访问它。@EJP真的-谢谢。@EJP看在上帝的份上,您能将其添加为答案吗?@sᴜʀᴇsʜᴀᴛᴛᴀ EJP评论不是答案-这只是观察以改进问题唯一不太令人满意的借口是FileNotFoundException也是一个IOException,而catch似乎只是检查是否抛出了IOException,而不是考虑到它已经被捕获。+1您是对的。现在它很奇怪-毫无疑问。但是f可能是null,一个null指针异常选项将被抛出,没有人知道NullPointerException是否在IOException中。我不理解你的想法。Null指针是RuntimeException。你不应该检查这些异常。1.不要认为类及其继承不会更改!即使编译器也不认为继承会更改!2.
NumberFormatException
是一个错误RuntimeException
也一样,你真的应该检查这些异常!@PeterRader这从头到尾都是胡说八道。(1)newfilenotfoundexception()
不会抛出任何类型的IOException。
(2)FileNotFoundException
和NullPointerException
在两个方向上都不是继承关系。(3)编译器知道每个构造函数和方法抛出什么,而不“查看构造函数”:它在目标代码中。(4)Java检查所有检查的异常:没有“忽略性能”。@EJP 1.编译器只知道当前JRE/JDK版本的objectcode。在本例中,本机方法fillInStackTrace
抛出一个IOException
,该异常在RuntimeException
的构造函数中被调用(FileNotFoundException也使用)使用:.2。我可以使用动态代理从NullPointerException
以及D:\DNN-Project\DNN-Project\src\main\java\exceptionsAndAssertions\RethowTest.java:16: unreported exception java.io.IOException; must be caught or declared to be thrown
throw e;
^
1 error
HelloWorld.java:9: warning: unreachable catch clause
} catch (IOException e) {
^
thrown type FileNotFoundException has already been caught
1 warning