자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많음
- InputStream, OutputStream, java.sql.Connection 등의 예시가 있음
- 이러한 자원 중 상당수가 안전망으로 finalizer를 활용하고 있지만 finalizer는 그리 믿을만하지 못함
전통적으로는 이러한 경우 try-finally많이 쓰였다
- 그러나 자원이 둘 이상이면 try-finally 방식은 코드가 너무 지저분해짐
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try{
return br.readLine();
}
finally{
br.close()
}
}
- try-finally 문에서 미묘한 결점이 있음 ⇒ try 블록과 finally 블록 모두에서 예외가 발생할 수 있는데 stack trace에는 finally 블록의 예외만 나오게 될 것임. try 예외를 finally가 삼켜버리게 되어 디버깅이 어려움
자바 7의 try-with-resources 덕에 앞의 문제 해결됨
- 이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 함
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))){
return br.readLine();
}
}
- readLine()과 코드에서 나타나지 않는 close 호출 양쪽에서 예외가 발생하면 close에서 발생한 예외는 숨겨지고 readLine에서 발생한 예외가 기록됨
- 또한 숨겨진 예외들도 그냥 버려지지는 않고 스택 추적 내역에 suppressed 꼬리표를 달고 출력됨 ⇒ 자바 7의 Throwable에 추가된 getSuppressed 메서드를 이용하면 프로그램 코드에서 가져올 수도 있음