当前位置: 首页 > 知识库问答 >
问题:

声明多个有效的最终资源时,使用资源尝试是否不安全?

丁阎宝
2023-03-14

由于Java9,我们可以有效地使用最终变量与资源。

下面的示例显示了一种情况,其中一个资源初始化引发异常。

    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语句带来的安全性。

有人能确认一下是不是真的吗?如果是肯定的,为什么我们要在多个资源中使用这种语法并冒这个风险?

共有2个答案

应翰飞
2023-03-14

为了使try-with-Resources机制发挥作用,您应该将初始化代码放入try中。您的初始化似乎发生1行之前。如果你愿意做:

  public static void main(String[] args) {
    try (Resource1 r1 = new Resource1(); Resource2 r2 = new Resource2()) {
      System.out.println("TryWithResources.main() try");
    } catch (Exception e) {
      System.out.println("TryWithResources.main() catch");
    }
  }

这将打印:

TryWithResources.Resource1.close()
TryWithResources.main() catch

因此,您的代码应该是这样的:“我想自动关闭r1r2,但我更喜欢自己初始化它”

我的版本应该是这样的:“我想自动关闭r1r2,并且我想将其初始化为try块的一部分”

陈俊郎
2023-03-14

我认为您假设初始化发生在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语句中创建资源,毕竟在资源关闭后使用它是没有意义的。

 类似资料:
  • 不管错误情况如何,使用资源尝试是否总是关闭资源?我的意思是考虑以下代码: 会一直关闭吗?我读过Oracle文档,其中说: 无论try语句是正常完成还是突然完成,它都将关闭 因此无论程序正常运行还是抛出异常,它都将起作用。但是,类似或崩溃的情况怎么办?我知道这些条件对块不起作用。那么,使用资源尝试失败的条件是否存在? 这只是我请求的好奇心,谁能说明这一点吗?

  • 我知道,如果资源已实现自动关闭,您通过尝试传递的资源将自动关闭。到现在为止,一直都还不错。但是,当我有几个我想要自动关闭的资源时,我该怎么办呢。带插座的示例; 所以我知道套接字将被正确关闭,因为它在try中作为参数传递,但是输入和输出应该如何正确关闭呢?

  • 根据Oracle文档 try with resources语句是声明一个或多个资源的try语句。资源是一个对象,在程序完成后必须关闭它。try with resources语句确保在语句末尾关闭每个资源。任何实现java的对象。AutoCloseable,其中包括实现java的所有对象。伊奥。可关闭,可用作资源 如果资源未实现AutoCloseable,则无法在try块中声明,必须在主体部分中声明

  • 问题内容: 我是的新手,我想知道对于资源来说,我是否必须为每个添加一个,否则它将与上面的代码一起使用 问题答案: 通过在 块中声明所有资源,可以尝试将资源与多个资源一起使用,并且此功能是 Java 7中 引入的,而不是 Java 8中 引入的。如果有多个资源,则可以如下所示 在此示例中,该语句包含两个用分号分隔的声明: ZipFile 和 BufferedWriter 。当它紧随其后的代码块终止时

  • 这是一种向可观察的客户列表中添加新行星的方法。 我想知道我是否正确使用资源尝试,以及自动关闭是否工作。 我的问题是,这部分需要被封闭在一个try-catch块中,还是自动关闭。

  • 我想使用try with resource来切换上下文,但try()似乎无法在不声明变量的情况下使用资源,这使得代码不那么优雅。例如 和用法: 但是我在try()上得到了Syntext错误。只有当我这样写的时候:它通过编译。最优雅的方法是什么? 最新消息 因为在一些答案中,人们不明白我想做什么,所以我会尝试更好地解释。我试图以一种更优雅的方式实现以下逻辑: