Java 라이브러리에는 close 메서드를 호출하여 직접 닫아줘야 하는 자원들이 많다.
대표적인 예로는 InputStream, OutputStream, java.sql.Connection이 좋은 예이다.
자원을 닫는 방식은 클라이언트가 놓치기 쉬워, 예측할 수 없는 성능 문제로 이어지기도 한다.
이러한 문제에대한 안전망으로 finalizer를 활용하고 있지만 Item8에서 공부한 내용처럼 언제 어떻게 동작할지 모르기 때문에 믿을만하지 못하다.
그래서 전통적으로 많이 사용되어온 방식은 try-finally가 많이 사용되었다.
다음 예제는 실제로 취업 준비시절에 JSP에서 사용하였던 제 코드입니다
public static void close(Connection con, Statement stmt) {
try {
if (stmt != null) {
stmt.close();
stmt = null;
}
if (con != null) {
con.close();
con = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
안전한 방식이지만 close가 늘어날때마다 복잡해지고 close메서드를 제대로 구현하지 못하고 놓칠 가능성도 충분하다.
또한 try와 finally안에서 예외가 발생할 확률이 있는데 이러한 경우 finally에서 또 try-finally를 사용하여 보기조차 힘들고 실제로 디버깅 하기도 힘들것입니다.
이러한 문제를 해결하기위해서 Java7에서는 try-with-resources를 제공합니다.
이러한 문제를 해결하기 위해서는 해당 자원이 AutoCloseable 인터페이스를 구현해야 합니다.
AutoCloseable는 void를 반환하는 단순 close()메서드만 존재합니다
public interface AutoCloseable {
void close() throws Exception;
}
꼭 회수해야 하는 자원을 다룰 때는 try-finally 보다 try-with-resources를 사용하도록 하자.
코드는 더 짧아지고 만들어지는 예외 정보도 훨씬 유용하다.
다음은 AutoCloseable를 직접 implements하여 직접 구현한 테스트 코드입니다.
try-with-resources를 사용하였으며 내부 메서드를 실행한뒤 close를 실행한 결과를 확인할 수 있습니다.
class AutoCloseableExample implements AutoCloseable{
@Override
public void close() throws Exception {
System.out.println("AutoCloseable close() 호출");
}
public void print() {
System.out.println("print 실행 !!");
}
}
public class AutoCloseableApplication {
public static void main(String[] args) throws Exception{
try(AutoCloseableExample a = new AutoCloseableExample()) {
a.print();
}
}
}
//실행 결과
print 실행 !!
AutoCloseable close() 호출