整理Effective Java書中Item 9: Prefer try-with-resources to try-finally心得筆記

主旨

蠻多lib提供使用資源後必須手動呼叫close關閉資源,符合開閉原則(OCP),但往往就有人沒有好好遵守,最後造成記憶體洩漏問題。

點出問題

以前被常會看到在finally裡面將資源關閉的寫法如下,基本上沒甚麼問題。

    BufferedReader br = new BufferedReader(new FileReader("c:/data.txt"));
    try {
        for (String line = br.readLine(); line != null; line = br.readLine()) {
            System.out.println(line);
        }
    } finally {
        br.close();
    }

但是如果同時有兩個資源就會變成這樣,看了心情實在是很差,一點也不優雅。

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/data.txt");
        OutputStream out = response.getOutputStream();
        try {
            try {
                byte[] data = new byte[1024];
                int length = -1;
                while ((length = in.read(data)) != -1) {
                    out.write(data, 0, length);
                }
            } finally {
                out.close();
            }

        } finally {
            in.close();
        }

    }

當Java7以後的try-with-resources的把問題一次都解決了。

    try (BufferedReader br = new BufferedReader(new FileReader("c:/data.txt"))) {
        for (String line = br.readLine(); line != null; line = br.readLine()) {
            System.out.println(line);
        }
    }

以及

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        try (InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/data.txt");
                OutputStream out = response.getOutputStream()) {
            byte[] data = new byte[1024];
            int length = -1;
            while ((length = in.read(data)) != -1) {
                out.write(data, 0, length);
            }
        }

    }

小結

很明顯的在必須關閉資源時,使用try-with-resources程式碼更短更清楚,也不用擔心忘記資源的問題。