Dev Book

[Effective Java] Item9. try-finally보다는 try-with-resources를 사용하라

Jemlog 2022. 5. 20. 19:11

우리는 흔히 자원을 닫아주는 close 메서드를 사용할때 try-finally 안에서 처리해준다.

static String firstLineOfFile(String path) throws IOException {

BufferedReader br = new BufferedReader(new FileReader(path));
try{
return br.readLine();
}
finally {
 br.close(); // finally 블록 안에서 close 메서드 호출!
}
}

위의 방법을 사용했을때의 문제점은 크게 두가지가 있다.

  • 자원을 두개 이상 사용하면 구조가 복잡해진다.
  • 예외가 정상적으로 표시되지 않는다.

두번째 문제점에 대해 조금 더 알아보자.

 

예외가 중첩으로 일어날때, 가장 중요한 예외는 가장 먼저 발생한 예외이다. 만약 위의 코드의 try 문 내부의 readLine()에서 예외가 터지고, 결과적으로 finally 문의 br.close()도 예외가 터졌다고 생각해보자.

이 경우 readLine의 예외 메세지는 br.close에게 먹혀버린다. 이는 디버깅을 힘들게 만든다. 

 

이런 문제점을 깔끔하게 해결할 수 있는 방법이 자바 7에 등장한 try-with-resources 구문이다.

 

try-with-resources

static String firstLineOfFile(String path) throws IOException {

try(BufferedReader br = new BufferedReader(new FileReader(path)))
{
return br.readLine(); 
}
}

형태는 try구문의 매개변수 자리에 우리가 사용하는 자원을 명시해주고, 블록 안에서 실제 자원을 사용한다. 

try-with-resources를 사용하려면 우리가 사용하는 자원이 AutoCloseable 인터페이스를 구현하고 있어야 한다. 많은 자원들이 이미 AutoCloseable 인터페이스를 구현해놓았다. 

 

try-finally 구문의 두번째 문제로 제시했던 예외가 먹히는 경우를 어떻게 try-with-resources가 해결했는지 살펴보자.

위의 사진을 보면 4번째 줄에 Suppressed라고 적혀있는 것을 알 수 있다. try-finally였다면 먹혀버렸을 예외들까지 suppressed라는 이름으로 모두 출력된다. 

 

이처럼 try-with-resources는 간결함과 예외의 누락방지까지 모두 챙겼기때문에 자원 정리를 위해서는 꼭 AutoCloseable을 구현 후(이미 구현되어있는 클래스들이 많다.) try-with-resources를 사용하자.