研究以下方法:
static private void foo() {
try {
throw new FileNotFoundException();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
尽管最后一个catch块实际上无法到达,但此代码编译良好。
现在让注释throw new FileNotFoundException();
行
执行:
糟糕!我们看到
Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body
奇怪。为什么Java对这些情况使用双重标准?
static private void foo(FileNotFoundException f) {
try {
throw f;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
工作以及构造函数调用
[我注意到在不同版本的Java编译器上,我看到的编译此代码的结果不同。
public class RethowTest {
public static void main(String[] args) {
try {
throw new FileNotFoundException();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
throw e;
}
}
}
在我的本地计算机上: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
http://www.compileonline.com/compile_java_online.php(Javac 1.7.0_09)-
HelloWorld.java:9: warning: unreachable catch clause
} catch (IOException e) {
^
thrown type FileNotFoundException has already been caught
1 warning
可达性规则在Java 8 JLS 14.21(和Java 7)中定义如下:
如果满足以下两个条件,则可以到达捕获块C:
C的参数类型是未经检查的异常类型或Exception或Exception的超类, C的参数。(如果包含表达式的最里面的语句是可到达的,则该表达式可到达。)
请参见§15.6中有关表达式的正常和突然完成。- try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或是其子类。
注意,规则不禁止您的示例代码。第二个捕获块不符合第二个要点的标准。
((在示例的原始版本中,您捕获了Exception
。可及性推理将有所不同,但答案是相同的-有效代码。)
这是不一致的吗?以您的示例为例,您可能会说是这样。
为什么他们没有在可达性规则中解决这个问题?我不知道。您需要询问Java设计师!!但是:
可及性规则的
formulation可能需要更加复杂才能处理。规范中额外的(不必要的?)复杂性值得关注。
potential
另一方面,我无法想到他们
无法在规范中解决此“不一致”的技术原因。
catch
发出警告消息。那没问题。允许Java编译器对(技术上)合法的Java代码发出警告。 如果它们是错误,从技术上讲,这将是编译器的错误……根据我对JLS的阅读。
catch (Exception ...)
块将捕获运行时异常。从原则上讲,它永远不会到达。FileNotFoundException
是已检查的异常。一个catch块只有在try块中的某个东西抛出它或其子类之一时才可以到达。
[响应请求]
new FileNotFoundException()
,则称为类FileNotFoundException
的构造函数。在此构造函数中,可以通过调用本机方法fillInStackTrace
从理论上引发IOException-编译器可能不知道构造函数的内容,可能会抛出IOException
。[查看本文:https://community.oracle.com/thread/1445008?start=0示例。
如果编译器在每次出现时都在构造函数FileNotFoundException()
中使用它:忽略了Java的性能开销。]