-
Try-Finally 대신 Try-with-Resource 사용하라JAVA/Effective java 2021. 1. 4. 10:31
- 자바 라이브러리에는
InputStream
,OutputStream
그리고java.sql.Connection
과 같이 정리(close)가 가능한 리소스가 많다. - 하지만 그런 리소스를 사용하는 클라이언트 코드가 보통 리소스 정리를 잘 안 하거나 잘못하는 경우가 있다.
12345678910111213141516171819public class FirstError extends RuntimeException {}public class SecondException extends RuntimeException {}public class MyResource implements AutoCloseable {public void doSomething() throws FirstError {System.out.println("doing something");throw new FirstError();}@Overridepublic void close() throws SecondException {System.out.println("clean my resource");throw new SecondException();}}cs - 다음의 코드는 doSomething에서 에러가 나면 close는 호출되지 못한다.
- 따라서 고전적인 try-finally로 바꿔보자.
- 에러가 날때 리소스를 반환하는 고전적인 처리방법이다.
- 하지만 다음의 코드는 문제가 있다.
- try 안에 try 하는 상황을 보면 코드가 장황해지고 close를 해주는 코드를 작성하기가 난감해진다.
- 또 에러가 났을 때 스택 프레임과 같은 원리로 최초의 문제부터 보고 싶지만
- doSomething 에러 발생 -> close 에러 발생이라면 close의 SecondError만 보이게 된다.
- 즉 이 코드에서 예외가 발생하면
SecondException
이 출력되고FirstException
은 덮힌다. 즉 안 보인다. - 그러면 문제를 디버깅하기 힘들어진다. 또한 중복으로 try-catch를 만들어야 하는 경우에도 실수를 할 가능성이 높다.
- 자바 7에 추가된 Try-with-Resource를 사용하면 코드 가독성도 좋고, 문제를 분석할 때도 훨씬 좋다.
- 왜냐면 Try-Finally를 사용할 때처럼 처음에 발생한 예외가 뒤에 발생한 에러에 덮이지 않기 때문이다.
- 뒤에 발생한 에러는 첫번째 발생한 에러 뒤에다 쌓아두고(suppressed) 처음 발생한 에러를 중요시 여긴다.
- 따라서 디버깅을 하기가 굉장히 편해진다.
- myResource 인스턴스 두 개를 할당하고 myResource.doSomething에서 예외가 나도
- 두 인스턴스 모두 close를 호출해 주는 것을 확인할 수 있다.
- 그리고
Throwable
의getSuppressed
메소드를 사용해서 뒤에 쌓여있는 에러를 코딩으로 사용할 수도 있다. catch
블록은 Try-Fianlly와 동일하게 사용할 수 있다.
참고 자료
'JAVA > Effective java' 카테고리의 다른 글
equals를 재정의하려거든 hashCode도 재정의하라 (0) 2021.01.14 equals는 일반 규약을 지켜 재정의 하라 (0) 2021.01.11 Finalizer와 Cleaner는 피하라 (0) 2021.01.03 더이상 쓰지 않는 객체 레퍼런스는 없애자 + Weak Reference (0) 2021.01.02 불필요한 객체를 만들지 말자 (0) 2021.01.01 - 자바 라이브러리에는