java - 声明多个有效的最终资源时,try-with-resource 是否不安全?
问题描述
从 Java 9 开始,我们可以在 try-with-resources 中有效地使用最终变量。
下面的示例展示了其中一个资源初始化引发异常的情况。
public static void main(String[] args) {
Resource1 r1 = new Resource1();
Resource2 r2 = new Resource2(); // exception will be thrown
try (r1; r2) {
System.out.println("TryWithResources.main() try");
} catch (Exception e) {
System.out.println("TryWithResources.main() catch");
}
}
static class Resource1 implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("TryWithResources.Resource1.close()");
}
}
static class Resource2 implements AutoCloseable {
public Resource2() {
throw new RuntimeException();
}
@Override
public void close() throws Exception {
System.out.println("TryWithResources.Resource2.close()");
}
}
当我运行这个示例时,我得到的唯一输出是 RuntimeException,这意味着 Resource1 没有关闭。这是意料之中的,因为它没有在 try-with-resources 中初始化。
但是,这是预期的结果,还是我错过了什么?
因为,如果这实际上是它应该工作的方式,那么在我看来,这种新语法实际上消除了许多最初由 try-with-resources 语句带来的安全性。
有人可以确认是否真的是这样吗?而且,如果是肯定的,为什么我们会在多个资源中使用这种语法并冒这个风险?
解决方案
我认为您假设“初始化”发生在try
语句中。构造函数在到达之前抛出异常try-with-resources
。换句话说,该行try (r1; r2) {
本身并不初始化资源,它只是将它们称为变量。它不同于以try
块为单位初始化资源:
try (r1; Resource2 r2 = new Resource2()) { // this causes r1 to close if r2 throws an exception
话虽如此,您的观点是正确的,即新语法(访问最终变量)提供了灵活性,但代价是可能无法关闭先前创建的资源(如您的案例所示)。就我个人而言,我从来没有理由使用这种新语法。我想不出在语句中不创建资源的充分理由try
,毕竟在资源关闭后使用资源没有任何意义。
推荐阅读
- javascript - 重新排列数组以使键具有值
- r - 如何在 ggdensity() 中调整绘图标题的大小?
- ansible - 无法继续进行_items 和注册
- c# - 未创建 NLog 数据库
- javascript - 使用 Python 中的 JSON 为 Google Visualizations Gauge 提供数据
- html - 在 Edge 浏览器中显示 flex 不适用于对齐内容
- python - 使用 plistlib 更新现有的 plist 方向
- spring-boot - 在 Spring Boot 中使用 @PostPersit 更新 SQL 列中的所有条目
- python - 为什么 MySQL 电报机器人不起作用?
- android - 未解决的参考:list_item、Kotlin、android-studio。无法访问布局文件