Item 9. close 처리해야하는 resource는 try-with-resource를 이용하자

2019. 3. 12. 17:19Java/Effective Java

반응형

자바 라이브러리 중에는, close메서드로 직접 닫아줘야하는 resource가 많다.
( 예를들면 입출력 관련 자원들인 InputStream, OutputStream, Connection ... )

이 때, close를 처리하지 않으면 성능 저하의 문제를 일으키기에 반드시 닫아줘야 한다.

프로그램 실행 중에 에러가 발생되었다 하더라도 close 처리는 반드시 처리가 되어야 한다.

우리는 이런 경우에 흔히 try-finally 블럭을 이용하여 처리한다.
바로 아래와 같이!

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {
  private static final int BUFFER_SIZE = 8 * 1024;

  public static void main(String[] args) throws IOException {
    copy("D:/1.txt", "D:/copy.txt");
  }

  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();
    }
  }
}

close 해야할 resource 가 2개 이상일 경우에는 위와 같이 try-finally 블럭의 갯수가 늘어나 보기가 좋지 않다.

그런데 그런 문제 뿐만아니라 try 블럭과 finally 블럭 모두에서 에러가 발생되었을 경우에 try 블럭에서 나타난 에러는 나타나지 않고 finally블럭에서 발생된 에러만 로그에 출력되어 디버깅에 어려움을 겪을 수 있다는 단점이 있다.

이에 대한 해결책이 바로 try-with-resources 구조이다.


try-finally 블럭 말고 try-with-resources 를 사용하여 자원 해제를 자동으로 처리하자!

try-with-resources 구조를 사용하기 위해선 자원이 AutoCloseable 인터페이스를 implements 해야 한다.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Test {
  private static final int BUFFER_SIZE = 8 * 1024;

  public static void main(String[] args) throws IOException {
    copy("D:/1.txt", "D:/copy.txt");
  }

  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);
      }
    }
  }
}

자원해제를 해야하는 resource의 선언을 try 에 정의하는 방식이다.

try-with-resource 방식은 모양이 직관적이라는 장점도 있지만,
그 외에도 try-finally 방식에서 발생되는 문제도 해결해준다.

try내부와 close할때 예외가 동시에 발생되었을 때, close발생 예외는 숨겨줍니다.
숨겨준다라는 말에서 알 수 있듯, 필요에 따라 예외 발생에 관한 메시지 등을 읽어들일 수 있습니다.

또한, catch 블럭도 추가할 수 있어, 예외 발생시에 대한 처리도 추가할 수 있습니다.

728x90
반응형