결론적으로 이 책에서는 모든 경우에서 try-finally를 사용하지 말고 자바 7에 도입된 try-with-resources를 사용하라고 권장한다.
아래에서 그 이유에 대해 알아보자.
자바 라이브러리에는 InputStream, OutputStream, java.sql.Connection처럼 close 메소드를 호출해야 하는 리소스가 많다.
클라이언트에서 직접 호출
클라이언트 코드에서 놓치는 경우가 많아 성능 문제가 발생한다. (까먹을 수도, 예외 발생으로 처리가 안될 수도..)
아래 코드로 예시를 들면, br.readLine() 메소드에서 IOException이 발생할 경우, close는 호출되지 않고 스트림이 메모리에 남게 된다.
public static String inputString() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String result = br.readLine();
br.close();
return result;
}
finalizer
안전망으로 finalizer를 활용할 수도 있지만 보장할 수 없다.(아이템 8)
try-finally
요약 : 가독성 문제, 예외 처리 문제로 디버깅 확인 어려움
그래서 전통적인 방식으로 try-finally가 쓰였다. 아래 코드는 br.readLine() 메소드에서 예외가 발생하더라도 정상적으로 close하게 된다.
public static String inputString() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
return br.readLine();
} finally {
br.close();
}
}
그러나 아래 코드를 보면 close를 여러번 해주어야 할 경우, 코드가 상당히 지저분해진다.
public static void inputAndWriteString() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
try {
String line = br.readLine();
bw.write(line);
} finally {
bw.close();
}
} finally {
br.close();
}
}
무엇보다 try-finally의 더 큰 문제가 있다. 디버깅이 어려워진다.
inputString 메소드에서 기기 문제가 발생하면 readLine이 정상적으로 실행되지 못하고 예외를 던지게 되고, 마찬가지로 close 메소드도 예외를 던지게 된다.
finally 블록에서의 예외가 try 블록에서의 예외를 삼켜 finally 블록의 예외만 체크하게 된다. 최초 원인인 예외를 제대로 알 수 없다는 것..
물론 코드를 작성하여 체크를 할 수 있으나, 지저분해지기 때문에 추천하지 않는다.
try-with-resources을 사용하자
위의 문제점을 모두 해결해주는 것이 try-with-resources이다.
이를 사용하기 위해서는 AutoCloseable 인터페이스를 구현해야 한다.
AutoCloseable 인터페이스는 close 메소드만 정의해놓은 간단한 형태이다.
public interface AutoCloseable {
void close() throws Exception;
}
앞서 try-finally로 구현했던 코드를 try-with-resources로 구현하면 아래와 같다.
public static String inputString() throws IOException {
try (BufferedReader br = new BufferedReader(new InputStream(System.in))) {
return br.readLine();
}
}
가독성도 좋고, 예외가 발생해도 디버깅이 편리하다 !
앞서 상황처럼 readLine과 close 모두 예외가 발생할 경우, readLine의 예외를 보여주며 close의 예외는 suppressed 상태가 되어 stackTrace시 Suppressed되어있다는 메시지로 출력된다. suppressed 상태가 된 예외는 자바 7부터 도입된 getSuppressed 메소드로 가져올 수 있다.
요약
가독성도 좋고, 예외 정보도 훨씬 유용해 디버깅이 편한 try-with-resources를 사용하자.
이를 사용하기 위해 AutoCloseable 구현하는 것도 까먹지 말자..
'Language > Java' 카테고리의 다른 글
| [effective java] 아이템 11. equals를 재정의하려거든 hashCode도 재정의하라. (0) | 2023.03.09 |
|---|---|
| [effective java] 아이템 10. equals는 일반 규약을 지켜 재정의하라. (0) | 2023.03.09 |
| [effective java] 아이템 8. finalizer와 cleaner 사용을 피하라. (0) | 2023.03.08 |
| [effective java] 아이템 7. 다 쓴 객체 참조를 해제하라. (0) | 2023.03.04 |
| [effective java] 아이템 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라. (0) | 2023.03.02 |