Home [Effective Java] Item71. 필요 없는 검사 예외 사용은 피하라!
Post
Cancel

[Effective Java] Item71. 필요 없는 검사 예외 사용은 피하라!

Item71. 필요 없는 검사 예외 사용은 피하라!

검사 예외

  • 결과를 코드로 반환하거나 비검사 예외를 던지는 것과 달리, 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다.
  • 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다.
    • 검사 예외를 던질 수 있다고 선언됐으면, 호출 시 catch 블록을 두어 예외를 처리하거나 더 바깥으로 전파해야만 하기 때문이다.
    • 또, 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없다.
  • API를 제대로 사용한다면 발생하지 않는 예외이거나, 프로그래머가 예외에 대한 조치를 취하는 것에 유의미한 의미가 없는 경우라면 비검사 예외를 사용하는 게 좋다.
  • 검사 예외를 여러 개 던져야 하는 상황이라면 어쩔 수 없이 예외 처리를 하겠지만, 단 하나의 검사 예외를 던지는 경우라면 그 하나 때문에 catch 블록을 사용해야 하고, 스트림에서 직접 사용하지 못하는 문제도 발생하니 검사 예외를 안 던지는 방법이 있는지 고민해보자.

검사 예외를 회피하는 방법

  • 적절한 결과 타입을 담은 옵셔널을 반환하는 것이다.

    • 검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환하면 된다.
    • 이 방식은 예외 발생 이유를 알려줄 수 없다는 단점이 존재한다. (예외를 사용한다면 구체적인 예외 타입, 그 타입이 제공하는 메서드를 활용해 부가 정보를 제공하는 것도 가능하다.)
  • 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 바꾸는 방식이다.

    • 이 방식에서 첫 번째 메서드는 예외가 던져질지 여부를 boolean 값으로 반환한다.
    1
    2
    3
    4
    5
    
    try {
      	obj.action(args);
    } catch (TheCheckedException e) {
      	... // 예외 상황에 대처한다.
    }
    
    • 리팩터링 전 코드다.
    1
    2
    3
    4
    5
    
    if(obj.actionPermitted(args)){
      	obj.action(args);
    } else {
      	... // 예외 상황에 대처한다.
    }
    
    • 리팩터링 후의 코드다.
      • 프로그래머가 이 메서드가 성공하리라는 걸 안다거나, 실패 시 스레드를 중단하길 원한다면 이처럼 사용해도 된다.
      • actionPermitted는 상태 검사 메서드에 해당하므로, 외부 동기화 없이 여러 스레드가 동시 접근 가능하거나 외부 요인에 의해 상태가 변할 수 있다면, 이 방법은 적절치 못하다. actionPermitted와 action 호출 사이에 객체 상태가 변할 수도 있기 때문이다. (아이템 69 참조)

핵심 정리

  • 꼭 필요한 곳에서만 사용한다면 검사 예외는 프로그램의 안전성을 높여준다.
    • 남용한다면 고통스러운 API를 낳는다.
  • API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자.
  • 복구 가능하고, 호출자가 그 처리를 하길 원한다면, 우선 옵셔널 반환을 고민하자.
    • 옵셔널만으로 상황 처리에 충분한 정보를 제공할 수 없다면 검사 예외를 던지자.
This post is licensed under younghwani by the author.

[Effective Java] Item70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라!

[Effective Java] Item72. 표준 예외를 사용하라!

Comments powered by Disqus.