728x90
try-finally는 사용하는 자원이 많아질수록 코드가 지저분해진다. 이건 많이들 경험해 보았을 것이다.
static String firsLineOfFile(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[1000000];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}finally {
out.close();
}
}finally {
in.close();
}
}
많이 더러워진다!
게다가 두 코드 예제조차 결점을 가지고 있다.
예를 들어 기기에 물리적인 문제가 생긴다면 firstLineOfFile 메서드 안의 readLine 메서드가 예외를 던지고, 같은 이유로 close 메서드도 실패할 것이다.
이런 상황이라면 두 번째 예외가 첫 번째 예외를 완전히 집어삼켜 버린다. 그러면 스택 추적 내역에 첫 번째 예외에 관한 정보는 남지 않게 되어, 실제 시스템에서의 디버깅을 몹시 어렵게 한다.
이런한 문제들이 자바 7에서 나온 try-with-resources 덕에 모두 해결되었다.
이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다.
대부분의 자바 라이브러리들이 이미 AutoCloseable을 구현하거나 확장해두었다.
이제 사용 방법을 알아보자.
static String firsLineOfFile(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[1000000];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
가독성도 훨씬 좋아졌을 뿐더러, 문제를 진단하기도 훨씬 쉬워진다.
try-with-resources에서도 catch절을 사용하여 예외를 처리할 수 있다.
정리
꼭 회수해야 하는 자원을 다룰 때는 try-finally말고 try-with-resources를 사용하자.
예외는 없다. 코드는 더 짧고 분명해지고, 만들어지는 예외 정보도 유용하다.
728x90
'☕️ Java > 이펙티브 자바' 카테고리의 다른 글
[Effective Java] 아이템 15 - 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2022.02.11 |
---|---|
[Effective Java] 아이템 10 - equals는 일반 규약을 지켜 재정의하라 (0) | 2022.02.05 |
[Effective Java] 아이템 8 - finalizer와 cleaner 사용을 피하라 (0) | 2022.02.04 |
[Effective Java] 아이템 7 - 다 쓴 객체 참조를 해제하라 (0) | 2022.02.03 |
[Effective Java] 아이템 6 - 불필요한 객체 생성을 피하라 (0) | 2022.02.03 |