<aside> 📎 ITEM9 try-finally 보다는 try-with-resources를 사용하라
</aside>
자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다.
InputStream, OutputStream 등의 IO 라이브러리
→ 코드를 이용해 메모장을 열고, close 하지 않은 상태에서 직접 메모장을 실행하는 경우 위와 같은 에러메세지를 확인할 수 있다.
java.sql.Connection 등의 JDBC 사용을 위한 라이브러리
어떠한 이유(오류 또는 개발자의 실수)에 의해서 close가 안되면, 프로그램에 문제가 생길 수 있다.
이런 자원의 상당수가 안전망으로 finalizer를 활용하고 있긴 하나, 그리 믿을만하지는 못하다.
자원의 닫힘을 보장해주는 수단 : try-finally
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
**try** { return br.readLine(); }
**finally** { br.close(); }
}
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(); }
}
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try { return br.**readLine**(); }
finally { br.**close**(); }
}
특히 예외는 try 블록과 finally 블록 모두에서 발생할 수 있는데, 위 예시에서 기기에 문제가 생기는 경우
→ 이런 상황이 발생하면 스택 추적 내역에 첫번째 예외에 관한 정보는 남지 않는다 : 디버깅이 어려워짐
해결책의 등장 : try-with-resources
AutoCloseable 인터페이스 : void 타입의 close 메서드 하나만 덩그러니 정의된 인터페이스
public interface AutoCloseable { void close() throws Exception; }
Closeable?
try-with-resources가 모든 객체의 close를 호출해주지는 않음
AutoCloseable을 구현한 객체만 close가 호출된다.
public abstract class BufferedReader implements AutoCloseable { ... }
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}