Skip to content

Latest commit

 

History

History
59 lines (52 loc) · 2.9 KB

item71.md

File metadata and controls

59 lines (52 loc) · 2.9 KB

아이템 71. 필요 없는 검사 예외 사용은 피하라

검사 예외

장점

  • 제대로 사용하면 API와 프로그램의 질을 높일 수 있다.
  • 발생한 문제를 프로그래머가 처리하여 안정성을 높이게 해준다.
    • catch 블록을 두어 예외를 붙잡아 처리하거나 더 바깥으로 던져 문제를 전파해야 한다.

단점

  • 사용자에게 부담을 준다.
  • 스트림 안에서 직접 사용할 수 없다. (아이템 45~48 참고)
  • 남용하면 고통스러운 API가 된다.

기준

  • API를 제대로 사용해도 발생할 수 있는 예외이거나 프로그래머가 의미 있는 조치를 취할 수 있는 경우라면 부담을 감수할 수 있다고 본다.
  • 위 둘의 조건 중 어디에도 해당하지 않는다면, 비검사 예외를 활용한다.
    • 아래와 같은 경우라면, 비검사 예외를 그냥 쓰자.
    • 예외 상황에서 복구할 수 없는 경우!
    } catch (TheCheckedException e) { 
        throw new AssertionError(); // 비검사 예외로 처리
    }
    
    } catch (TheCheckedException e) {
        e.printStackTrace();
        System.exit(1); // 시스템 종료
    }
  • 이미 다른 검사 예외가 있는 경우와 달리 검사 예외가 단 하나의 검사 예외를 던질 때가 가장 부담이 크다.

회피

  • 검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하는 것이다. (아이템 55)
    • 검사 예외 대신 단순히 빈 옵셔널 반환
    • 이 방식의 단점은 예외가 발생한 이유를 알려주는 부가 정보를 담을 수 없다는 점이다.
    • 예외를 사용한다면, 구체적인 예외 타입과 그 타입이 제공하는 메서드들을 활용해 부가 정보를 제공할 수 있다.
  • 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 변경한다.
    • 첫 번째 메서드는 예외가 던져질지 여부를 boolean 값으로 반환한다.
    • 더 아름답진 않지만, 더 유연하다.
    // before
    try {
        Obj.action(args);    
    } catch (TheCheckedException e) {
        //do something
    }
    
    // after
    if (obj.actionPermitted(args)) {
        obj.action(args);
    } else {
        //do something
    }
    • 모든 상황에 적용할 수는 없다.
    • actionPermitted 메서드는 상태 검사 메서드에 해당하므로 아이템 69에서 말한 단점도 그대로 적용된다.
      • 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나, 외부 요인에 의해 상태가 변할 수 있다면 이 리팩터링은 적절하지 않다.
      • 각 메서드 호출 사이에 객체의 상태가 변할 수 있기 때문이다.
    • 상태 검사 메서드가 action 메서드의 작업 일부를 중복 수행한다면 성능에서 손해이므로 적절하지 않다.