아이템 69. 예외는 진짜 예외 상황에만 사용하라. - ksw6169/effective-java GitHub Wiki
예외를 사용한 반복문의 단점
- 예외를 사용한 반복문은 코드를 헷갈리게 하고 성능을 떨어뜨린다. (코드를 try-catch 블록 안에 넣으면 JVM이 적용할 수 있는 최적화가 제한된다.)
- 반복문 안에 버그가 숨어 있다면 흐름 제어에 쓰인 예외가 이 버그를 숨겨 디버깅을 훨씬 어렵게 한다.
// 예외를 완전히 잘못 사용한 반복문
try {
int i = 0;
while (true)
range[i++].climb();
} catch (ArrayIndexOutOfBoundsException e) {}
예외는 오직 예외 상황에서만 쓰여야 한다.
예외는 절대 일상적인 제어 흐름용으로 쓰여선 안된다. 대신에 쉽게 이해되는 표준 관용구를 사용하고, 성능 개선을 목적으로 과하게 머리를 쓴 기법은 자제하라.
API 설계 시에도 예외는 오직 예외 상황에서만 사용하라.
잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. 또한 특정 상태에서만 호출할 수 있는 '상태 의존적' 메소드를 제공하는 클래스는 '상태 검사' 메소드도 함께 제공해야 한다. (Iterator 인터페이스의 next와 hasNext가 각각 상태 의존적 메소드와 상태 검사 메소드에 해당한다.)
상태 검사 메소드 대신 Optional 혹은 특수한 값을 반환할 수도 있다.
상태 검사 메소드 대신 올바르지 않은 상태일 때 빈 옵셔널 혹은 null 같은 특수한 값을 반환하는 방법도 있다. 상태 검사 메소드, 옵셔널, 특정 값 중 하나를 선택하는 지침은 다음과 같다.
- 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인으로 상태가 변할 수 있다면 옵셔널이나 특정 값을 사용한다. (상태 검사 메소드와 상태 의존적 메소드 호출 사이에 객체의 상태가 변할 수 있기 때문이다.)
- 성능이 중요한 상황에서 상태 검사 메소드가 상태 의존적 메소드의 작업 일부를 중복 수행한다면 옵셔널이나 특정 값을 선택한다.
- 다른 모든 경우에는 상태 검사 메소드 방식이 조금 더 낫다. 가독성이 살짝 더 좋고, 잘못 사용했을 때 발견이 쉽다. 상태 검사 메소드 호출을 깜빡했다면 상태 의존적 메소드가 예외를 던져 버그를 확실히 드러낼 것이다. 반면에 특정 값은 검사하지 않고 지나쳐도 발견하기가 어렵다. (이 점은 옵셔널에는 해당되지 않는다.)
핵심 정리
- 예외는 예외 상황에서만 쓰도록 설계되었기 때문에 정상적인 제어 흐름에서 사용해서는 안된다.
- 또한 이를 프로그래머에게 강요하는 API를 만들어서도 안된다.
참고 자료
- Effective Java 3/E