try {
int i = 0;
while(true)
range[i++].climb();
} catch (ArrayIndexOutOfBoundsException e) {
}
무슨 일을 하는지 절혀 알 수 없는 코드이다. 이 코드는 배열을 순회하는데, 끔찍한 방식으로 진행하고 있다. 무한 루프를 돌다가 배열의 끝에 도달해 예외가 발생하면 끝을 내는 것이다.
이 코드는 성능 향상을 위해서 작성했다고 생각할 수 있지만, 표준 관용구(for-loop)보다 훨신 느리다.
예외는 오직 예외 상황에서만 써야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안된다.
이 원칙은 API 설계에도 적용된다. 잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. 특정 상태에서만 호출할 수 있는 '상태 의존적' 메서드를 제공하는 클래스는 '상태 검사' 메서드도 함께 제공해야 한다. ex) (iterator inteface 의 next, hasNext) 그리고 별도의 상태 검사 덕분에 다음과 같은 표준 for-loop을 사용할 수 있다
for (Iterator<Foo> i = collection.iterator(); i.hasNext(); ) {
// loop....
}
Iterator가 hasNext() 를 제공하지 않았다면 그 일을 클라이언트가 대신해야만 했다.
상태 검사 메서드 대신 사용할 수 있는 선택지도 있다. 빈 옵셔널, 혹은 null 같은 특수한 값을 반환하는 방법이다.
예외는 예외 상황에서 쓸 의도로 설계 되었다. 정상적인 제어 흐름에서 사용해서는 안된다.