try-finally 보다는 try-with-resources를 사용하라
try-finally
static String firstLineOfFile(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 블록 모두에서 발생할 수 있다. 예컨대 기기에 물리적인 문제가 생긴다면 readLine 메서드가 예외를 던지고, close 메서드도 실패하게 된다. 이런 상황이라면 두번째 예외가 첫 번째 예외를 완전히 집어삼켜서 스택 추적 내역에 첫 번째 예외에 관한 정보는 남지 않게 되어 디버깅이 어려워진다.
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)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
이 구조를 사용하려면 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다. readLine과 close 호출 양쪽에서 예외가 발생해도 숨겨진 예외들이 버려지지 않고, 스택 추적 내역에 suppressed 꼬리표를 달고 출력된다. 또한, 자바 7에서 Throwable에 추가된 getSuppressed 메서드를 이용하면 프로그램 코드에서 가져올 수도 있다.
꼭 회수해야 하는 자원을 다룰 때는 try-finally 대신 try-with-resources를 사용하자. 코드는 더 짧고 명확해지고, 만들어지는 예외 정보도 훨씬 유용하다. 그리고 정확하고 쉽게 자원을 회수할 수 있다.
Comments