개발 공부 기록하기/01. JAVA & Kotlin

짧은 코멘트와 함께하는 이펙티브 자바) #9 try-finally 보다는 try-with-resources를 사용하라

lannstark 2020. 9. 26. 14:38

짧은 코멘트

  1. 당연히 try with resources를 사용해야 한다.
  2. JDK 7부터 try with resources를 사용할 수 있게 되었는데 혹시 프로젝트가 JDK 6이라면.... (와.. AWS AMI에서 JDK8도 사라지고 JDK11을 권장하고 있는데, JDK 6이요..?) 다른회사로 도망쳐야 한다

try-finally 보다는 try-with-resources를 사용하라

자바 라이브러리에는 close 메소드를 호출하여 직접 닫아줘야 하는 자원이 많다. (ex. InputStream, OutputStream, java.sql.Connection) 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다

전통적으로 자원 닫힘을 보장하는 수단으로는 try - finally가 쓰였다

static String firstLineOfFile(String path) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    return br.readLine();
  } finally {
    br.close();
  }
}

위의 전형적인 try finally 예시는 나쁘지 않지만 자원을 하나 더 사용하는 경우는 조금 복잡해진다

static void copy(String src, String dest) throws IOException {
  InputStream in = new FileInputStream(src);
  try {
    OutputStream out = new FileOutputStream(dest);
    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();
  }
}

이런 복잡함을 해결하기 위해 JAVA 7에서는 try - with -resources 구문이 나오게 되었다. 이 구조를 사용하기 위해서는 해당 자원이 AutoCloseable 인터페이스를 구현해야 한다

첫 번째 코드에 try - with - resources를 사용하면 이렇게 된다

static String firstLineOfFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  return.br.readLine();
  }
}

두 번째 코드에 try - with - resources를 사용하면 이렇게 된다.

static void copy(String src, String dest) throws IOException {
  try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest)) {
    byte[] buf = new byte[BUFFER_SIZE]
    int n;
    while((n = in.read(buf)) >= 0)
      out.write(buf, 0, n);
  }
}

훨씬 깔끔해진 것을 확인할 수 있다.

try - with - resources 에서도 catch 절을 사용할 수 있다

static String firstLineOfFile(String path, String defaultVal) {
  try (Buffered br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  } catch (IOException e) {
    return defaultVal;
  }
}