728x90
try-finally
보다는 try-with-resources
를 사용하라
- 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어질 수 있다.
- 상당수가 안전망으로
finalizer
를 사용하지만finalizer
는 그리 믿을만 하지 않다.
try-finally : 전통적으로 쓰이는 방법
코드가 지저분하다.
package effectivejava.chapter2.item9.tryfinally;
import java.io.*;
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
// 코드 9-2 자원이 둘 이상이면 try-finally 방식은 너무 지저분하다! (47쪽)
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();
}
}
public static void main(String[] args) throws IOException {
String src = args[0];
String dst = args[1];
copy(src, dst);
}
}
예외가 숨겨져 디버깅이 어렵다.
package effectivejava.chapter2.item9.tryfinally;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TopLine {
// 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽)
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
public static void main(String[] args) throws IOException {
String path = args[0];
System.out.println(firstLineOfFile(path));
}
}
readLine()
과close()
에서 예외 발생시close()
예외만 표시되어 디버깅이 어렵다.
try-with-resources (권장) 🌟
- 이 구조를 사용하려면
AutoClosable
인터페이스를 구현해야한다.
public class MyResource implements AutoCloseable {
public void doSomething() {
System.out.println("리소스 사용 중");
}
@Override
public void close() throws Exception {
System.out.println("리소스 해제");
}
}
// 사용 예시
try (MyResource resource = new MyResource()) {
resource.doSomething();
} // try 블록이 끝나면 resource.close()가 자동으로 호출
단순하고 짧다.
package effectivejava.chapter2.item9.trywithresources;
import java.io.*;
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
// 코드 9-4 복수의 자원을 처리하는 try-with-resources - 짧고 매혹적이다! (49쪽)
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);
}
}
public static void main(String[] args) throws IOException {
String src = args[0];
String dst = args[1];
copy(src, dst);
}
}
try 블록이 끝날 때 자동으로 구현했던 close()가 호출된다.
InputStream과 FileOutputStream은 이미 AutoCloseable을 구현하고 있기 때문에 별도로 close()를 구현할 필요가 없다.
Java 표준 라이브러리의 많은 I/O 클래스들은 이미
AutoCloseable
이 구현되어 있으므로, 우리가 직접 만드는 클래스에서만AutoCloseable
을 구현하면 된다.
디버깅하기 편하다.
- 숨겨진 예외도 스택 추적 내역에 숨겨졌다는 꼬리표를 달고 출력된다.
Throwable
의getSuppressed
메서드를 이용해 예외를 가져올 수 있다.
try (FileInputStream in = new FileInputStream("file.txt")) {
throw new RuntimeException("작업 중 예외 발생!"); // 주 예외
} catch (Exception e) {
// 1. 주 예외 출력
System.out.println("주 예외: " + e.getMessage());
// 2. getSuppressed()로 숨겨진 예외들 확인
Throwable[] suppressedExceptions = e.getSuppressed();
for (Throwable suppressed : suppressedExceptions) {
System.out.println("숨겨진 예외: " + suppressed.getMessage());
}
}
catch
로 다수의 예외를 처리할 수 있다.
package effectivejava.chapter2.item9.trywithresources;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TopLineWithDefault {
try (FileInputStream in = new FileInputStream("file.txt");
FileOutputStream out = new FileOutputStream("output.txt")) {
// 파일 처리
} catch (FileNotFoundException e) {
// 파일을 찾을 수 없을 때
System.out.println("파일이 없습니다: " + e.getMessage());
} catch (IOException e) {
// 그 외 입출력 예외
System.out.println("입출력 오류: " + e.getMessage());
}
}
결론
- 꼭 회수해야하는 지원을 다룰 때는
try-finally
말고try-with-resources
를 사용하자. - 코드는 더 짧고 분명해지고, 만들어지는 예외 정보도 훨씬 유용하다.
728x90
'Java > effective java' 카테고리의 다른 글
[Effective Java] Item 10. equals는 일반 규약을 지켜 재정의하라 (0) | 2025.01.13 |
---|---|
[Effective Java] 3장. 모든 객체의 공통 메서드 - 0. 들어가기 (0) | 2025.01.12 |
[Effective Java] Item 8. finalizer와 cleaner 사용을 피하라. (0) | 2025.01.12 |
[Effective Java] Item 7. 다 쓴 객체의 참조를 해제하라. (0) | 2025.01.12 |
[Effective Java] Item 6. 불필요한 객체 생성을 피하라. (0) | 2025.01.12 |