【发布时间】:2020-02-13 10:00:58
【问题描述】:
我偶然发现了如下代码:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
这段代码让我吃惊,因为它看起来run()-方法能够抛出Exception,因为它捕获Exception然后重新抛出它,但该方法没有声明抛出Exception,显然不需要。这段代码编译得很好(至少在 Java 11 中)。
我的期望是我必须在run()-方法中声明throws Exception。
额外信息
以类似的方式,如果doSomething 被声明为抛出IOException,那么即使Exception 被捕获并重新抛出,也只需要在run() 方法中声明IOException。
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()方法不需要在上面的代码sn-ps中声明throws Exception? (如果我要添加它,IntelliJ 会警告我 Exception 永远不会被抛出)。
【问题讨论】:
-
有趣。你用的是什么编译器?如果它是 IDE 编译器,请检查
javac- 我遇到过 Eclipse 编译器更宽松的情况。 -
我可以在 openjdk-8 上重现此行为。值得注意的是,使用
-source 1.6标志进行编译会引发预期的编译错误。使用源代码兼容性 7 进行编译不会引发编译错误 -
自 Java 7 以来,编译器似乎是 smarter,并且对可能引发的实际异常进行了更多检查。
-
这个问题不是重复的,答案可以在我提供的链接中找到
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. -
currently marked duplicate 肯定是相关的,但没有提供足够详细的答案 IMO。 一个链接到 JLS 在 cmets 到答案那里,除了没有信息。