我偶然发现代码看起来像这样:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
这段代码使我感到惊讶,因为它看起来像run()
-method能够抛出an Exception
,因为它可以捕获Exception
然后重新抛出它,但是该方法未声明为throw Exception
,显然不需要。这段代码可以很好地编译(至少在Java 11中)。
我的期望是我必须throws Exception
在run()
-method中声明。
额外的信息
以类似的方式,如果doSomething
被声明为throw,IOException
那么即使被捕获并重新抛出,也只需IOException
在run()
-method中进行声明Exception
。
void run() throws IOException {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() throws IOException {
// ... whatever code you may want ...
}
题
Java通常喜欢清晰,这种行为背后的原因是什么?一直都是这样吗?Java语言规范中的哪些内容允许run()
方法不需要throws Exception
在上面的代码段中声明?(如果我要添加它,IntelliJ会警告我Exception
永远不要抛出该警告)。
我可以在openjdk-8上重现此行为。值得注意的是,使用该
—
Vogel612 '19
-source 1.6
标志进行编译会产生预期的编译错误。使用源兼容性7 进行编译不会引发编译错误
这个问题不是重复的,可以在我提供的链接中找到答案
—
michalk
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions : 1. 1. The try block is able to throw it. 2. There are no other preceding catch blocks that can handle it. 3. It is a subtype or supertype of one of the catch clause's exception parameters.
在当前标记重复的肯定是相关的,但不IMO提供足够详细的答案。在该答案的注释中,有一个指向JLS 的链接,除此之外没有任何信息。
—
西蒙·福斯伯格 Simon Forsberg)
javac
-我一直在遇到Eclipse编译器更为宽大的情况。