java - 包装多个 AutoCloseables

标签 java autocloseable

try-with-resources 很好,但在我看来,在创建包装多个 AutoCloseable 的类时,它仍然不足以进行有效的资源管理对象。例如,考虑

import java.io.*;

class AutocloseableWrapper implements AutoCloseable {
    private FileReader r1;
    private FileReader r2;

    public AutocloseableWrapper(String path1, String path2) throws IOException {
        r1 = new FileReader(path1);
        r2 = new FileReader(path2);
    }

    @Override
    public void close() throws IOException {
        r1.close();
        r2.close();
    }

    public static void main(String[] args) throws IOException {
        try (AutocloseableWrapper w = new AutocloseableWrapper("good-path", "bad-path")) {
                System.out.format("doing something\n");
                throw new IOException("doing something in main");
            }
    }
}

此包装器至少存在两个问题:

  1. 如果“bad-path”无效并导致对 r2 的赋值抛出异常,则 r1 不会关闭。
  2. 如果包装器构造成功,但随后 r1.close 抛出异常,则 r2 未关闭。

所有这些问题都可以解决,但是即使只包装两个资源,编写包装器也变得非常重要并且容易出错:

import java.io.*;

class AutocloseableWrapper implements AutoCloseable {
    private FileReader r1;
    private FileReader r2;

    public AutocloseableWrapper(String path1, String path2) throws IOException {
        r1 = new FileReader(path1);
        try {
            r2 = new FileReader(path2);
        }
        catch (IOException e) {
            try {
                r1.close();
            }
            catch (IOException e2) {
                e.addSuppressed(e2);
            }
            throw e;
        }
    }

    @Override
    public void close() throws IOException {
        IOException e = null;
        try {
            r1.close();
        }
        catch (IOException e1) {
            e = e1;
        }

        try {
            r2.close();
        }
        catch (IOException e2) {
            if (e == null)
                throw e2;
            else {
                e.addSuppressed(e2);
                throw e;
            }
        }
    }

    public static void main(String[] args) throws IOException {
        try (AutocloseableWrapper w = new AutocloseableWrapper("good-path", "bad-path")) {
                System.out.format("doing something\n");
                throw new IOException("doing something in main");
            }
    }
}

是否有一些帮助类或任何其他方法可以使编写包装器更容易?

最佳答案

您应该启用由编译器解包的语法代码...您可以在这里找到 Oracle 文章:- http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html

说到这个问题,如果你有一个包装器,你可以做这样的事情

@Override
public void close() throws IOException {
    Throwable t = null;
    try {
        r1.close();
    } catch (Throwable t1) {
        t = t1;
        throw t1;
    } finally {
        if (t != null) {
            try {
                r2.close();
            } catch (Throwable t2) {
                t.addSuppressed(t2);
            }
        } else {

            r2.close();
        }
    }
}

注意:由于 Java 中的精确重新抛出功能,这将起作用 7

关于java - 包装多个 AutoCloseables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24705055/

相关文章:

java - 日历给出错误的星期几

Java 8 使用流和收集器映射到集合的子列表条目

java - JBOSS+SPRING 请求参数 URL 编码

java - Tomcat 运行服务而不是 Web 应用程序

java - 如果我只需要查找一次位置,是否需要调用 requestLocationUpdates() ?

java - 未分配变量的 PrintWriter 在使用后会关闭吗?

java - 在 Finalize 方法中触发用户可见的异常

apache-poi - 与资源一起使用时是否需要处理 SXSSFWorkbook

java - 如何在由 spring 关闭的可自动关闭 bean 的单元测试中覆盖 close 方法