ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Try-Finally 대신 Try-with-Resource 사용하라
    JAVA/Effective java 2021. 1. 4. 10:31
    • 자바 라이브러리에는 InputStream, OutputStream 그리고 java.sql.Connection과 같이 정리(close)가 가능한 리소스가 많다.
    • 하지만 그런 리소스를 사용하는 클라이언트 코드가 보통 리소스 정리를 잘 안 하거나 잘못하는 경우가 있다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public 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();
        }
        @Override
        public 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를 호출해 주는 것을 확인할 수 있다.

     

    • 그리고 ThrowablegetSuppressed 메소드를 사용해서 뒤에 쌓여있는 에러를 코딩으로 사용할 수도 있다.
    • catch 블록은 Try-Fianlly와 동일하게 사용할 수 있다.

    참고 자료 


    이펙티브 자바

Designed by Tistory.