Item9 - try ~ finally 보다 try-with-resources를 사용하라

2023. 11. 19. 20:52Book/이펙티브 자바

 

 

요약 : 장점 밖에 없는 try-with-resource

 

자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다.

InputStream, OutputStream, Connection 등이 좋은 예다. 자원 닫기는 클라이언트가 놓치기 쉬워 예측할 수 없는 성능 문제로 이어지기도 한다. 전통적으로는 try-finally가 쓰였지만 try-with-resource를 사용하기로 하자.

 

try-finally 단점1 : 가독성

========try-finally=========

public class Copy {
    private static final int BUFFERED_SIZE = 8 * 1024;

    static void copy(String src, String dst) throws IOException {
        InputStream in = new FileInputStream(src);
        try {
            OutputStream out = new FileOutputStream(dst);
            try {
                byte[] buf = new byte[BUFFERED_SIZE];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }
}

========try-with-resource=========

public class Copy {
    private static final int BUFFERED_SIZE = 8 * 1024;

    static void copy(String src, String dst) throws IOException {
        try (InputStream   in = new FileInputStream(src);
             OutputStream out = new FileOutputStream(dst)) {

            byte[] buf = new byte[BUFFERED_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        }
    }
}

 

 

try-finally 단점2 : 마지막 예외만 보이는 점

============try-finally=============

public class TopLine {

    static String firstLineOfFile(String path) throws IOException {
        BufferedReader br = new BadBufferedReader(new FileReader(path));
        try {
            return br.readLine();
        } finally {
            br.close();
        }
    }

    public static void main(String[] args) throws IOException {
        System.out.println(firstLineOfFile("pom.xml"));
    }
}

============try-with-resource=============

public class TopLine {

    static String firstLineOfFile(String path) throws IOException {
        try (BufferedReader br = new BadBufferedReader(new FileReader(path))) {
            return br.readLine();
        }
    }

    public static void main(String[] args) throws IOException {
        String path = args[0];
        System.out.println(firstLineOfFile(path));
    }
}

 

위 코드에서 br.readLine() 메서드에서 예외가 발생하고 br.close() 메서드에서도 예외가 발생한다고 하면 예외로깅은 어떻게 보일까?

 마지막에 발생한 br.close() 메서드 예외만 보인다. 디버깅을 할 때 가장 중요한 예외는 첫번째 예외인데 이 단점은 매우 크다. 물론 try ~ catch 문을 중첩으로 사용해 addSuppress 메서드를 사용해 모든 예외를 보일 수 있게 만들 수 있지만 역시 가독성이 크게 떨어진다.

 

 try-with-resource를 사용하면 모든 예외를 볼 수 있고 가독성도 좋다.