[java]try-with-resource

1

java7 부터 아래와 같이 try-catch-finally 문을 이용해 자원해제를 하던 것이 try-with-resource 를 이용해 더 간결하게 코드작성이 가능해 졌다.

  • try catch finally 방식 예제
      try {
          scanner = new Scanner(new File("test.txt"));
          while (scanner.hasNext()) {
              System.out.println(scanner.nextLine());
          }
      } catch (FileNotFoundException e) {
          e.printStackTrace();
      } finally {
          if (scanner != null) {
              scanner.close();
          }
      }
    
  • try with resource 방식 예제
      try (Scanner scanner = new Scanner(new File("test.txt"))) {
          while (scanner.hasNext()) {
              System.out.println(scanner.nextLine());
          }
      } catch (FileNotFoundException fnfe) {
          fnfe.printStackTrace();
      }
    
  • 자원 해제가 필요한 객체를 try 안에 선언하면 close 메소드를 자동으로 호출하게 된다 단 close가 호출되는 것은 AutoCloseable을 구현한 객체에만 해당된다.

2

AutoCloseable 를 구현하는 클래스 만들어 보자

public static void main(String args[]) {
    try (CustomResource cr = new CustomResource()) {
        cr.doSomething();
    } catch (Exception e) {
    }
}

private static class CustomResource implements AutoCloseable {
    public void doSomething() {
        System.out.println("Do something...");
    }

    @Override
    public void close() throws Exception {
        System.out.println("CustomResource.close() is called");
    }
}
  • 실행하면 아래처럼
    Do something...
    CustomResource.close() is called
    

3

조금더 심화해서

  • 여러 리소스는 세미콜론응로 구분해서 사용할수도 있음.
      try (Scanner scanner = new Scanner(new File("testRead.txt"));
          PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
          while (scanner.hasNext()) {
          writer.print(scanner.nextLine());
          }
      }
    
  • 리소스 해제는 처음 획득한 리소스가 제일 마지막에 해제된다
    public class AutoCloseableResourcesFirst implements AutoCloseable {
    
      public AutoCloseableResourcesFirst() {
          System.out.println("Constructor -> AutoCloseableResources_First");
      }
    
      public void doSomething() {
          System.out.println("Something -> AutoCloseableResources_First");
      }
    
      @Override
      public void close() throws Exception {
          System.out.println("Closed AutoCloseableResources_First");
      }
    }
    .
    .
    public class AutoCloseableResourcesSecond implements AutoCloseable {
    
      public AutoCloseableResourcesSecond() {
          System.out.println("Constructor -> AutoCloseableResources_Second");
      }
    
      public void doSomething() {
          System.out.println("Something -> AutoCloseableResources_Second");
      }
    
      @Override
      public void close() throws Exception {
          System.out.println("Closed AutoCloseableResources_Second");
      }
    }
    .
    .
    .
    private void orderOfClosingResources() throws Exception {
      try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst();
          AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) {
          af.doSomething();
          as.doSomething();
      }
    }
    

순서는 아래처럼 된다.

Constructor -> AutoCloseableResources_First
Constructor -> AutoCloseableResources_Second
Something -> AutoCloseableResources_First
Something -> AutoCloseableResources_Second
Closed AutoCloseableResources_Second
Closed AutoCloseableResources_First
  • 마지막으로 java9 이후부터는 아래처럼도 가능하다.
  • final 로 선언을 하거나 첫번째 할당 후에 변경되지 않은(사실상 final 변수)? 경우 자동으로 해제 가능하다.
final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}
  • 참고
    • https://www.baeldung.com/java-try-with-resources
    • 등등