try-finally보다는 try-with-resources를 사용하라
자바 라이브러리 내부의 close()
메서드
- 자바에서는 종종
.close()
메서드를 통해 자원을 닫아줘야 하는 경우가 있다.- 주로 외부의 리소스를 사용했을 때이다.
- 외부의 리소스는 로컬 PC 환경에 존재하는 리소스일 수도 있고, 네트워크로 연결된 다른 컴퓨터에 존재하는 리소스(
Connection
)일 수도 있다.
finalizer
를 안전망으로 활용하긴 하지만,item8
에서 배웠듯 딱히 믿을만하진 않다.
try-finally
를 이용하여 리소스 닫기
예제 1 - 반환할 자원이 1개일 때
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
- 멋지게
try-finally
로 리소스 반환을 하였다.
예제 2 - 반환할 자원이 2개일 때
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(src);
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
블록과finally
블록에서 전부 예외가 발생할 수 있는데,finally
블록의 예외가try
블록의 예외를 잡아먹게 된다.- 이 경우 디버깅이 매우 어려워질 수 있다.
try-with-resources
를 이용하여 리소스 닫기
try-with-resources
를 구현하는 것은 클래스에서AutoCloseable
을 상속받아close()
메서드만 구현해주면 된다.
예제 1 - 반환할 자원이 1개일 때
static String firstLineOfFile2(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
예제 2 - 반환할 자원이 2개일 때
static void copy2(String src, String dst) throws IOException {
try(InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(src)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}
}
try-with-resources
가 해결하는 문제
- 반환할 자원이 몇개더라도, 코드가 지저분해지지 않는다. 코드가 매우 깔끔해졌다.
- 예외 발생 시
close()
에서 발생한 예외는 숨겨지고readLine()
예외만 기록되어 디버깅하기 쉬워진다. - 모든 리소스에 대한 예외
catch
가 가능하기 때문에 예외를 묶어서 한번에 처리하기도 좋다. finally
에서 발생하는 예외가 사라지기 때문에 아래와 같은 코드 예제도 가능하다.
static String firstLineOfFile3(String path, String defaultValue) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (Exception e) {
return defaultValue;
}
}
예외가 터질 시에 기본값을 반환하는 예이다.
정리
- 리소스 회수 코드를 작성할 때는
try-finally
보다는try-with-resources
를 애용하자. - 코드가 더 짧고 분명해지고, 예외 정보도 훨씬 유용하다.
close()
를 까먹을 일도 없다.
반응형
'Java > 이펙티브 자바' 카테고리의 다른 글
이펙티브 자바, 쉽게 정리하기 - item 11. equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2021.12.29 |
---|---|
이펙티브 자바, 쉽게 정리하기 - item 10. equals는 일반 규약을 지켜 재정의하라 (0) | 2021.12.29 |
이펙티브 자바, 쉽게 정리하기 - item8. finalizer와 cleaner 사용을 피하라 (0) | 2021.12.27 |
이펙티브 자바, 쉽게 정리하기 - item7. 다 쓴 객체 참조를 해제하라 (0) | 2021.12.27 |
이펙티브 자바, 쉽게 정리하기 - item6. 불필요한 객체 생성을 피하라 (0) | 2021.12.26 |