Effective Java - 객체 생성과 파괴(3)

SeungHyuk Shin·2021년 9월 7일
0

Effective Java

목록 보기
3/26
post-thumbnail

아이템 9. try-finally 보다는 try-with-resources를 사용하라


자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다. 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다. 이런 자원 중 상당수가 안전망으로 finalizer를 활용하고는 있지만 finalizer는 그리 믿을만 하지 못하다.

전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다.

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[BUFFER_SIZE];
        int n;
        while((n = in.read(buf)) >= 0)
     		out.write(buf, 0, n);
            
    }finally {
      out.close();
    }
  }finally{
    in.close();
  }
}

믿기 어렵겠지만 훌륭한 프로그래머조차 이런 잘못을 흔히 저지른다. 예외는 try 블록과 finally 블록 모두에서 발생할 수 있는데, 예컨데 copy 메서드 안의 FileOutputStream 메서드가 예외를 던지고 같은 이유로 close 메서드도 실패할 것이다.

그러면 스택 추적내역에 첫 번째 예외 관한 정보는 남지않게되어 실제로 디버깅을 매우 어렵게한다.

이러한 문제들은 자바 7이 투척한 try-woth-resources 덕에 모두 해결되었다. 이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다.

다음은 try-with-resources를 사용해 코드를 재작성한 예이다.

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-with-resources 버전이 짧고 읽기 수월할 뿐 아니라 문제를 진단하기도 훨씬 좋다.

보통의 try-finally에서 처럼 try-with-resources에서도 catch 절을 쓸 수 있다.catch절 덕분에 try 문을 더 중첩하지 않고도 다수의 예외를 처리할 수 있다.

static String firstLineOfFile(String path, String defaultVal){
  try (BufferdReader br = new BufferedReader(new FileReader(path))) {
      return br.readLine();
    } catch (IOExcption e){
      return defaultVal;
    }
}

0개의 댓글