본문 바로가기

Java/Java SE, EE

[Java/Java SE, EE] try-with-resources 리소스 자동 닫기

자바 7 이전까지는 리소스를 안전하게 닫기 위해서 다음과 같은 코드를 사용합니다.

FileInputStream fis = null;

try {
   fis = new FileInputStream("file.txt");
} catch (IOException e) {
   // 리소스 사용 중 예외 발생
} finally {
   try {
      fis.close();
   } catch (IOException e) {
      // 리소스 반환 중 예외 발생
   }
}

try-with-resources

자바 7 이후부터 try-with-resources를 사용하면 예외 발생 여부와 상관없이 리소스를 안전하게 닫을 수 있습니다.

try (FileInputStream fis = new FileInputStream("file.txt")) {
   // 리소스 사용
} catch (IOException e) {
   // 리소스 사용 중 예외 발생
}

위의 예시 코드는 첫 예시 코드를 자바 7에서 다시 작성한 것입니다. 리소스 선언부가 try 키워드 이후에 이어지는 괄호()에 포함됩니다. try 블록이 정상적으로 종료되거나 또는 예외가 발생하게 되면 선언된 리소스는 자동으로 close() 메소드를 호출합니다.

복수 개의 리소스 처리

try-with-resources에서 2개 이상의 리소스를 사용하려면 다음과 같이 작성합니다. try () 구문에 여러 개 리소스를 선언하며, 각각의 리소스의 선언은 세미클론(;)으로 구분합니다.

try (FileInputStream fis = new FileInputStream("file-0.txt");
     FileOutputStream fos = new FileOutputStream("file-1.txt")) {
   // 리소스 사용
} catch (IOException e) {
   // 리소스 사용 중 예외 발생
   e.printStackTrace();
}

AutoCloseable

그렇다면 try-with-resources에서 사용 가능한 리소스는 어떤 것들이 있을까요? 다음 예시와 같이 String 클래스도 사용 할 수 있을까요?

try (String abc = new String("abc")) {
   // 리소스 사용
} catch (IOException e) {
   // 리소스 사용 중 예외 발생
}

예시 코드는 try () 구문에서 "Required type: AutoCloseable" 컴파일 오류가 발생합니다. 오류에 따르면 해당 구문에서는 반드시 java.lang.AutoCloseable 인터페이스를 구현하는 객체만 사용 할 수 있습니다.

public interface AutoCloseable {
    void close() throws Exception;
}

AutoCloseable 구현

우리가 직접 작성한 클래스도 java.lang.AutoCloseable 인터페이스를 구현하여 try-with-resources 구문에서 사용 할 수 있습니다.

public class CustomAutoCloseableExample implements AutoCloseable {
   public void handle() throws IOException {
      System.out.println("handle example ..");
      throw new IOException();
   }
   
   @Override
   public void close() throws IOException {
      System.out.println("auto closed !!");
   }
}

CustomAutoCloseableExample 클래스는 handle() 메소드 실행 도중 java.io.IOException을 발생시킵니다. 그리고 오버라이드된 close() 메소드가 호출되면 "auto closed !!"를 출력합니다.

try (CustomAutoCloseableExample example = new CustomAutoCloseableExample()) {
   example.handle();
} catch (IOException e) {
   e.printStackTrace();
}

CustomAutoCloseableExample 클래스는 java.lang.AutoCloseable 인터페이스를 구현하고 있으므로 try-with-resources 구문에서 사용 할 수 있습니다. try 블록에서는 해당 객체의 handle() 메소드를 호출합니다.

handle example ..
auto closed !!
java.io.IOException
	at Main$CustomAutoCloseableExample.handle(Main.java:16)
	at Main.main(Main.java:6)

실행 결과를 확인하면 객체가 try 블록에서 예외가 발생하자 오버라이드된 close() 메소드가 자동 호출되는 것을 확인 할 수 있습니다.