April 09, 2022
자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다. (InputStream, OutputStream, java.sql.Connection 등)
자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다. 이런 자원 중 상당 수가 안전망으로 finalizer를 활용하고는 있지만 믿을 만하지 못하다.(아이템 8)
전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다.
static String fisrtLineOfFile(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[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
try-finally 문을 제대로 사용한 앞의 두 코드 예제의 미묘한 결점
해결! -> 자바 7이 투척한 try-with-resources
이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다.
try-with-resources를 사용해 코드를 재작성해보자
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)
)
}
try-with-resources 버전이 짧고 읽기 수월할 뿐 아니라 문제를 진단하기도 훨씬 좋다.
try-with-resources에서도 catch 절을 쓸 수 있다. catch 절 덕분에 try 문을 더 중첩하지 않고도 다수의 예외를 처리할 수 있다.
static String firstLineOfFile(String path, String defaultVal) {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return defaultVal;
}
}