아이템9. try-finally 보다는 try-with-resources를 사용하라
2021-05-28 00:00:00 # Effective_Java
  • 자바 라이브러리에 존재하는 close 메서드를 필요로 하는 자원들이 있다. (예: InputStream, java.sql.Connection 등)
  • 전통적으로 try-finally가 많이 쓰였다.

try-finally

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;

// 자원을 하나 사용할 때
public class FinallyExample {
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
// 기기의 물리적인 문제가 생긴다면
try {
return br.readLine(); // 첫번째 예외 발생
} finally {
br.close(); // 두번째 예외 발생
}
// 결론적으로 첫번째 예외에 대한 추적 내역이 사라지게 된다.
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.*;

// 자원을 두 개 사용할 때
public class FinallyExample {
static String 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-with-resources 방식

  • 자바 7부터 추가됨
  • 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 함 (닫아야 하는 자원을 뜻하는 클래스를 작성할 때)
1
2
3
4
5
6
7
8
9
10
import java.io.*;

// 자원을 하나 사용할 때
public class WithResourcesExample {
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;

// 자원을 두 개 사용할 때
public class WithResourcesExample {
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);
}
}
}
  • 코드가 더 짧아지고 자원 선언에서 발생한 예외가 그 이후의 예외로 인해 사라지지 않는다.
  • catch 절도 동일하게 사용 가능하다.

핵심 정리

  • 꼭 회수해야 하는 자원을 다룰 때에는 try-finally 말고, try-with-resources를 사용하자.
  • 코드는 더 짧고 분명해진다.
  • 만들어지는 예외 정보도 훨씬 유용하다.