【问题标题】:Correctly closing resources in constructor and close method in case of error在错误的情况下正确关闭构造函数和关闭方法中的资源
【发布时间】:2021-03-20 16:37:52
【问题描述】:

给定一个AutoCloseableMyClass,它在其构造函数中创建多个SomeResource 类型的资源。 SomeResource 也实现了AutoCloseable 并且它的构造函数和它的close 方法都可能抛出一个IOException。我如何最好地确保:

  • a) 构造过程中发生故障时,构造函数会正确关闭所有打开的资源
  • b) close 方法在关闭其中一个资源时正确关闭所有资源以防万一。

这是示例类:

public class MyClass implements AutoCloseable {

    private final SomeResource resource1;
    private final SomeResource resource2;
    private final SomeResource resource3;

    MyClass() throws IOException {
        resource1 = new SomeResource();
        resource2 = new SomeResource();
        resource3 = new SomeResource();
    }

    @Override public void close() throws IOException {
        resource1.close();
        resource2.close();
        resource3.close();
    }
}

【问题讨论】:

    标签: java try-with-resources


    【解决方案1】:

    a) 构造函数不能使用 try-with-resources 或 try-finally,因为资源不会被关闭,以防资源创建成功。取而代之的是,在创建资源之后应该有一个 try-catch 块,以确保在创建资源后出现任何错误时关闭资源。在 catch 块内,必须重新抛出异常,以免丢失。

    b) close 方法可以使用 try-with-resource 块来确保所有资源都已关闭

    public class MyClass implements AutoCloseable {
    
      private final SomeResource resource1;
      private final SomeResource resource2;
      private final SomeResource resource3;
    
      MyClass() throws IOException {
        resource1 = new SomeResource();
        try {
          resource2 = new SomeResource();
          try {
            resource3 = new SomeResource();
          } catch (IOException | RuntimeException e) {
            closeIgnoreException(resource2);
            throw e;
          }
        } catch (IOException | RuntimeException e) {
          closeIgnoreException(resource1);
          throw e;
        }
      }
    
      private static void closeIgnoreException(AutoCloseable autoCloseable) {
        try { autoCloseable.close(); } catch (Exception ignore) {}
      }
    
      @Override
      public void close() throws IOException {
        try (resource1;
            resource2;
            resource3) {}
      }
    }
    

    在 Java 9 之前,try-with-resources 语句不接受任何引用。因此close方法必须通过以下方式实现:

      public void close() throws IOException {
        try (SomeResource r1 = resource1;
            SomeResource r2 = resource2;
            SomeResource r3 = resource3) {}
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-26
      • 2016-09-27
      • 2011-08-12
      • 1970-01-01
      • 2010-10-12
      相关资源
      最近更新 更多