声明多个有效的最终资源时,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语句中创建资源的充分理由,毕竟在资源关闭后使用它是没有意义的。

  • If you want a practical example of a use case for the newer feature, consider [this answer](https://stackoverflow.com/a/32232173/2711488). The method returns a `Stream` backed by JDBC resources. So it can’t use the ordinary `try(…)` as that would unconditionally close the resources before the Stream got returned to the caller. Only in the erroneous case, all resources should be closed safely before delivering the exception to the caller. When successful, a `Runnable` has to be registered at the `Stream` instance to close the already existing resources when the stream got closed by the caller.

以上是声明多个有效的最终资源时,try-with-resource不安全吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>