본문 바로가기
책읽고 정리/Effective Java

[Effective Java 3/E] 아이템9. try-finally보다는 try-with-resources를 사용하라

by jeonghaemin 2021. 6. 22.
728x90

자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다.(InputStream, OutputStream, java.sql.Connection 등)

자원 닫기는 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다.

안전망으로 fianlizer를 활용하기도 하지만 믿을만하지 못하다.(아이템 8)

전통적인 자원 닫힘 보장 수단 : try-finally

단점

  • 자원이 둘 이상이면 코드가 지저분해진다.
  • 두 번째 예외가 첫 번째 예외를 집어삼켜 버려 스택 추적 내역에 첫 번째 예외 정보는 남지 않게 되고, 디버깅을 어렵게 한다.
    • 아래 firstLineOfFile 메서드의 br.readLine()에서 예외가 발생하고, br.close() 실패하면 두 번째 예외가 첫 번째 예외를 삼켜버린다.
static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

(자바 7) 자원을 회수하는 최선책 : try-with-resources

  • 이 구조를 사용하려면 단순히 void close() 메서드 하나만 정의되어있는 AutoClosable 인터페이스를 구현해야 한다.
  • try블록을 벗어날 때 자동으로 close() 메서드가 호출된다.
  • try를 중첩하지 않고도 다수의 예외를 처리할 수 있다.
  • 숨겨진 예외들도 버려지지 않고, 스택 추적 내역에 '숨겨졌다(suppressed)'는 꼬리표를 달고 출력된다.
    • 자바 7의 Throwable에 추가된 getSuppressed 메서드를 사용하면 숨겨진 예외를 배열 형태로 받아올 수 있다.
static void copy(String src, String dst) throws IOException {
    try (InputStream in = new FileInputStream(src);
         OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new Byte[BUFFER_SIZE];
        int n;
        while((n = in.read(buf)) >= 0)
            out.write(buf, 0, n);
    }
}

꼭 회수해야 하는 자원을 다룰 때는 try-finally 말고, try-with-resources를 사용하자

댓글