我偶然发现代码看起来像这样:
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 中)。
我的期望我必须声明throws Exception
in the run()
-method.
额外的信息
以类似的方式,如果doSomething
被宣布抛出IOException
那么只有IOException
需要在run()
-方法,尽管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 ...
}
Question
Java通常喜欢清晰,这种行为背后的原因是什么?一直都是这样吗? Java 语言规范中允许的内容run()
方法不需要声明throws Exception
在上面的代码片段中? (如果我添加它,IntelliJ 会警告我Exception
永远不会被抛出)。
我还没有扫描过JLS
正如您在问题中所问的,所以请对这个答案持保留态度。我想发表评论,但它太大了。
我有时觉得好笑,怎么办javac
在某些情况下(例如您的情况)非常“聪明”,但留下了很多其他事情需要稍后处理JIT
。在这种情况下,只是编译器“可以告诉”只有一个RuntimeException
会被抓住的。这是显而易见的,这是你唯一扔进去的东西doSomething
。如果您将代码稍微更改为:
void run() {
try {
doSomething();
} catch (Exception ex) {
Exception ex2 = new Exception();
System.out.println("Error: " + ex);
throw ex2;
}
}
你会看到不同的行为,因为现在javac
可以说有一个新的Exception
你扔出的东西与你接住的东西无关。
但事情远非理想,您可以通过以下方式再次“欺骗”编译器:
void run() {
try {
doSomething();
} catch (Exception ex) {
Exception ex2 = new Exception();
ex2 = ex;
System.out.println("Error: " + ex);
throw ex2;
}
}
国际海事组织,因为ex2 = ex;
它不应该再次失败,但它确实失败了。
以防万一这是用编译的javac 13+33
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)