try {
int i = 0;
while (true)
range[i++].climb()
} catch (ArrayIndexOutOfBoundsException e) {
}
JVM은 배열에 접근할 때마다 경계를 넘지 않는지 검사하니, 그 하나를 생략해보고자 한 코드다.
하지만 잘못 됐다.
try-catch
블록 안에 넣으면 JVM이 적용할 수 있는 최적화가 제한된다.만약 버그가 숨어있었다면 이 예외가 버그를 숨겨 디버깅이 어려웠을 것이다.
예외는 예외 상황에서만 써라. 일상적인 제어 흐름용으로 쓰지 마라.
잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야한다.
특정 상태에서만 호출할 수 있는 상태 의존적
메서드를 제공하는 클래스는 상태 검사
메서드도 함께 제공해야 한다.
Iterator
인터페이스의 next
와 hasNext
가 각각 상태 의존적 메서드와 상태 검사 메서드에 해당된다. 이러한 메서드 덕분에 for 관용구를 사용할 수 있다. for-each도 내부적으로 hasNext를 사용
한다.List<Car> cars = new ArrayList<>();
for (Iterator<Car> i = cars.iterator(); i.hasNext();) {
...
}
haxNext
와 같은 상태 검사 메서드도 제공해야 한다.
List<Car> cars = new ArrayList<>();
try {
Iterator<Car> i = cars.iterator();
while (true) {
Car car = i.next();
}
} catch (NoSuchElementException e) {
}
이런 식으로 순회하면 안된다.
상태 검사 메서드 대신 빈 옵셔널이나 null을 반환할 수 도 있다.