Skip to content

Latest commit

 

History

History
114 lines (101 loc) · 3.74 KB

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

File metadata and controls

114 lines (101 loc) · 3.74 KB

자원을 직접 닫을 경우 try-finally 보다는 try-with-resources를 사용하라

엘리

💡 close 메서드를 호출해 직접 닫아줘야하는 자원에 try-with-resources를 적용해 안전하게 닫아주자!!

  • 예) InputStream, OutputStream, java.sql.Connection 등
  • 자원을 닫지 않으면 성능 문제로 이어질 수 있다!!

try-finally (Java7 이전)

변수1 = null;
변수2 = null;
try {
   변수1 = new 자원객체1();
   변수2 = new 자원객체2();
   변수1.작업();
   변수2.작업();
   ...
} finally {
   if (변수1 != null) 변수1.close();
   if (변수2 != null) 변수2.close();
}
  • 어떤 경우에도 자원을 반납하도록 구현하기위해 fianlly를 사용하게 된다.
  • null 여부를 추가로 검사해야한다.
  • close 해주는 걸 잊으면 그냥 끝..
디버깅의 어려움
  • 예외는 try 블록finally 블록 모두에서 발생할 수 있다.
  • 이럴 경우 fianlly 블록에서 발생한 예외만 남게되고 try 블록에서 발생한 예외는 알 수 없게 된다.

image

@Test
void throwExceptionTryFinally() throws IOException {
FileInputStream is = null;
BufferedInputStream bis = null;
try {
is = new FileInputStream("/Users/ellie/MyData/woowacourse/file.txt");
bis = new BufferedInputStream(is);
int data = -1;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
throw new IOException("try에서 에러 발생");
} finally {
if (is != null) {
is.close();
}
if (bis != null) {
bis.close();
}
throw new IOException("finally에서 에러 발생");
}
}

try-with-resources (Java7 이후)

try (변수1 = new 자원객체1();
     변수2 = new 자원객체2()) {
    ...
}

try-with-resources는 try(...)에서 선언된 객체들에 대해 try가 종료될 때 자동으로 close를 호출하여 자원을 해제해주는 기능을 제공한다.

  • Java7부터 제공한다.
  • 이때 해제하려는 자원의 객체에는 AutoCloseable 인터페이스가 구현되어 있어야한다. (아이템8 참고)

위의 경우가 아니라면 무조건 try-with-resources를 사용하자!!

  • 짧고 읽기 수월해진다.
  • close를 잊을 일이 없다.
  • 문제를 진단하기 좋아진다.
디버깅의 어려움 해소
  • try 블록close에서 모두 예외가 발생할 수 있지만 try 블록에서 발생한 예외가 기록된다.
  • 이때 close에서 발생한 예외는 숨겨지며, 스택 트레이스에 “Suppressed(숨겨짐)” 키워드로 출력된다.

image

public class CustomResource implements AutoCloseable {

  public void doSomething() {
    System.out.println("Do something...");
  }

  @Override
  public void close() {
    System.out.println("CustomResource.close() is called");
    throw new IllegalArgumentException("close에서 에러 발생");
  }
}
@Test
void throwExceptionTryWithResources() {
    try (CustomResource cr = new CustomResource()) {
        cr.doSomething();
        throw new IOException("try에서 에러 발생");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

** IntelliJ에서도 다음과 같이 try-fianlly로 자원을 해제할 경우 경고를 띄우며, try-with-rewources로의 변경을 권장하고 있다. image

Ref.