요약
•
예외는 진짜 예외일 때만 사용하자.
예외는 진짜 예외일 때만
try {
int i = 0;
while (true)
range[i++].climb();
} catch (ArrayIndexOutOfBoundException e) {
}
Java
복사
•
위 코드는 무한 루프를 돌다가 배열의 범위를 벗어나면 예외를 던지는 것을 잡아 끝내는 코드다.
for (Mountain m : range)
m.climb();
Java
복사
•
위 코드 대신 이처럼 작성을 하면 가독성도 좋고 직관적으로 작성할 수 있다.
•
첫 번째 코드와 같이 사용하면 세 가지 문제점이 있다.
◦
예외는 예외 상황에 쓸 용도로 설계되었는데, 이런 코드로 작성할 동기가 약하다.
◦
코드를 try-catch 블록 안에 넣으면 JVM이 적용할 수 있는 최적화가 제한된다.
◦
배열을 순회하는 표준 관용구는 JVM이 최적화해 없애준다.(배열을 순회하는 요소마다 배열이 끝나는지 검사하는 비용은 JVM이 최적화해 없애준다)
•
이와 같이 예외를 사용하는 경우에는 진짜 예외가 발생해야하는 상황에서만 사용하자. 위 코드처럼 일상적인 제어 흐름용으로 사용되어선 안된다.
•
잘 설계된 API라면 클러이언트가 정삭적인 제어 흐름에서 예외를 사용할 일이 없게 해야한다.
•
예외 발생을 try-catch가 아닌 Iterator의 hasNext()와 같은 상태 검사 메서드를 사용하거나, 옵셔널을 반환하고 null 같은 특수한 값을 반환하는 방법으로 미리 확인하자.
•
상태 검사 메서드, 옵셔널, 특수한 값 중 하나를 선택하는 지침은 다음과 같다.
◦
외부 동기화 없이 여러 스레드가 동시에 접근 가능하거나 외부 요인으로 상태가 변할 수 있다면, 상태 검사 메서드 호출 사이에 객체의 상태가 변할 수 있으므로 옵셔널이나 특수 값을 사용한다.
◦
성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 작업의 일부라도 중복 수행한다면 옵셔널이나 특수 값을 사용한다.
◦
위의 두 경우를 제외하면 상태 검사 메서드를 사용하는 것이 가독성이 더 좋고, 잘못 했을 때 발견하기가 쉽다.