【Effective Java 09】try-with-resources 优先于 try-finally

1. 使用 try-finally 关闭资源的缺点

Java 类库中包括许多必须通过调用 close 方法来手工关闭的资源。例如,InputStreamOutputStreamjava.sql.Connection。客户端经常会忽略资源的关闭,造成严重的性能浪费。虽然这其中的许多资源都有终结方法作为 “安全网”,但是效果并不理想。

长久以来,try-finally语句式确保资源会被适时关闭的最佳方法,就算法发生异常或者返回也一样。

public class BadDemo {
    public static String firstLineOfFiles(String path) throws IOException {
        // try-finally - No Longer the best way to close resources
        BufferedReader br = new BufferedReader(new FileReader(path));
        try {
            return br.readLine();
        } finally {
            br.close();
        }
    }
    public static void main(String[] args) {
        try {
            System.out.println(firstLineOfFiles("./hello.txt"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这看起来好像也不太坏。有这种感觉只是因为需要关闭的资源少。如果需要关闭的资源过多,很快就一团糟了。

public class BadDemo {

    public static final int BUFFER_SIZE = 4096;

    public static void copy(String src, String dst) throws IOException {
        InputStream is = new FileInputStream(src);
        try {
            OutputStream os = new FileOutputStream(dst);
            try {
                byte[] buf = new byte[BUFFER_SIZE];
                int n;
                while ((n = is.read(buf)) >= 0) {
                    os.write(buf, 0, n);
                }
            } finally {
                os.close();
            }
        } finally {
            is.close();
        }
    }
    public static void main(String[] args) {
        try {
            copy("a.txt", "b.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这样做太繁琐了。

2. 使用 try-with-finally 关闭资源

Java 7 引入了 try-with-resources 解决了该问题。要使用这个构造的资源,必须先实现 AutoCloseable 接口,其中包含了单个返回 voidclose 方法。 Java 类库与第三方类库中的许多类和接口,现在都实现或扩展了 AutoCloseable 接口。如果编写了一个类,它代表的是必须被关闭的资源,那么这个类也应该实现 AutoCloseable

public class GoodDemo {
    public static final int BUFFER_SIZE = 4096;

    public static void copy(String src, String dst) throws IOException {
        // The Best Way to close resources !
        try (
                InputStream is = new FileInputStream(src);
                OutputStream os = new FileOutputStream(dst)
        ) {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = is.read(buf)) >= 0) {
                os.write(buf, 0, n);
            }
        }

    }

    public static void main(String[] args) {
        try {
            copy("a.txt", "b.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用 try-with-resources 不仅使得代码更简单易懂,更容易进行诊断。如果 readLine 和 不可见的 close 方法都抛出异常,后一个抛出的异常就会被禁止,以保留第一个异常。

很显然,在处理必须关闭的资源时,始终要优先考虑使用 try-with-resources,而不是使用 try-finally。

posted on 2022-03-24 18:52  Silgm  阅读(68)  评论(0)    收藏  举报

导航