이펙티브 자바에서 객체의 생성과 소멸에서 제안하는 방법 중 하나이다. 기존 try-catch-finally으로 자원을 해제하는 것에서 Try-with-resource로 자원을 close 할 것을 권유하고 있다.
기존에 사용하던 try-catch 구문이다. finally 영역에서 자원을 해제한다.
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream("file.txt");
bis = new BufferedInputStream(is);
int data = -1;
while((data = bis.read()) != -1){
System.out.print((char) data);
}
} catch(Exception e){
e.printStackTrace();
throws e;
} finally {
// close resources
if (fis != null) is.close();
if (bis != null) bis.close();
}
try-catch-finally 구문 안에서 FileInputStream , BufferedInputStream 객체를 각각 사용하기 위해서 미리 선언한 후 null 값을 넣어주고 try 문에서 객체를 생성하여 finally에서 close하여 제거해주는 모습이다.
실행 결과는 위와 동일하다.
try (
FileInputStream fis = new FileInputStream("file.txt");
BufferedInputStream bis = new BufferedInputStream(is)
) {
int data = -1;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
코드를 보면 try(…)
안에서 객체를 선언하고 할당하는 모습이다. 각 구문에서 사용하기 위해 미리 선언한 후 객체를 생성해서 넣어준 반면, 이렇게 선언 및 할당하면 각 구문에서 사용할 수 있다. 이후 try 문을 벗어나면 Try-with-resource 에서는 선언 및 할당되었던 객체의 close() 메소드를 호출한다. 따라서 finally 문에서 별도로 close()를 호출할 필요가 없다.
try-with-resource 방법을 사용하기 위해서는 자원이 AutoCloseable 인터페이스를 반드시 구현해야 한다. 대부분 자바 라이브러리에서는 이를 구현해두어서 손쉽게 이용할 수 있다. ( 표준 )
만약 자바 표준이 아니어서 이를 상속하지 않고, 개인이 만든 클래스에서 try-with-resource 방법으로 자원이 해제되길 원한다면 Autocloseable을 구현하면 된다.
클래스를 만들어서 try-with-resource 방법으로 자원을 해제하기를 원하면 Autocloseable를 구현한다.
public class Person implements AutoCloseable {
public void hello() {
System.out.println("hello!");
}
@Override
public void close() throws Exception {
System.out.println("Person.close() is called");
}
}
레퍼런스
Effective Java - Joshua J. Bloch