728x90
반응형
자바 라이브러리에서 close메서드를 호출해 직접 자원을 닫아 줘야하는 경우가 있다.
(InputStream, OutputStream, java.sql.Connection 등..)
자원을 닫을 때 finalizer는 믿을 수 없다.
2022.02.24 - [책리뷰/이펙티브자바] - [이펙티브자바] 아이템8. finalizer와 cleaner사용을 피하라
전통적인 방법으로는 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();
}
}
위의 코드에서 readLine메서드가 예외를 던지고, 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();
}
}
자원이 늘어날 수록 코드는 지저분해지고 try블록과 finally블록에서 모두 예외가 발생할 때 정확한 디버깅을 할 수 없다.
try-with-resources
try-with-resources를 사용하려면 AutoCloseable 인터페이스를 구현해야한다.
static String firstLineOfFile(String path) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}
}
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);
}
}
읽기 수월하기도 하고 에러 발생시 첫 번째 에러를 스택에 노출한다.
즉, 첫 번째 코드에서 readLine에서 발생한 예외가 기록되고 close에서 발생한 예외는 숨겨진다.
(suppressed 숨겨졌다는 꼬리표를 달고 출력한다.)
❗️ 꼭 회수해야하는 자원을 다룰 때는 try-with-resources를 사용한다. 예외는 없다.
728x90
반응형
'책리뷰 > 이펙티브자바' 카테고리의 다른 글
[이펙티브자바] 아이템11. equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2022.03.04 |
---|---|
[이펙티브자바] 아이템10. equals는 일반 규약을 지켜 재정의하라 (0) | 2022.03.02 |
[이펙티브자바] 아이템8. finalizer와 cleaner사용을 피하라 (0) | 2022.02.24 |
[이펙티브자바] 아이템7. 다 쓴 객체 참조를 해제하라 (0) | 2022.02.23 |
[이펙티브자바] 아이템6. 불필요한 객체 생성을 피하라 (0) | 2022.02.15 |