java - 捕获异常并重新抛出它,但这不是异常
问题描述
我偶然发现看起来像这样的代码:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
这段代码让我感到惊讶,因为它看起来run()
- 方法能够抛出一个Exception
,因为它捕获Exception
然后重新抛出它,但是该方法没有声明为 throwException
并且显然不需要。这段代码编译得很好(至少在 Java 11 中)。
我的期望是我必须在 - 方法中throws Exception
声明run()
。
额外的信息
以类似的方式,如果doSomething
声明为 throw IOException
then 只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
永远不会抛出)。
解决方案
JLS
正如您在问题中所问的那样,我没有浏览过,所以请对这个答案持保留态度。我想发表评论,但它太大了。
我有时觉得很有趣,javac
在某些情况下(例如在您的情况下)如何非常“聪明”,但还有很多其他事情需要稍后处理JIT
。在这种情况下,只是编译器“可以告诉”只有 aRuntimeException
会被捕获。这很明显,这是你唯一投入的东西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;
}
}
IMO,因为ex2 = ex;
它不应该再次失败,但确实如此。
以防万一这是用javac 13+33
推荐阅读
- c# - DDD:聚合中的延迟加载
- java - Java Android OutputStreamWriter write() 未将参数传递给 php 文件
- android - 将 SQL 查询分解为访问内容提供程序的部分
- r - r 中两列之间的月间隔
- postgresql - Postgres 批量插入订单
- php - 带有参数的 MongoDB\Driver\Manager 连接 php
- mariadb - Mariadb 10.4 次要版本审查
- image-processing - 什么是合成图像?
- javascript - 下面的代码将向控制台输出什么,原因是什么?
- node.js - 从外部 url 下载 pdf 文件 - Heroku、NodeJS、Angular 7