자바는 문제 상황을 알리는 타입(throwable)으로 검사 예외, 런타임 예외, 에러를 제공한다.
언제 무엇을 사용해야 할까?
호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하라
검사 예외를 던지면 호출자가 그 예외를 catch로 잡아 처리하거나 더 바깥으로 전파하도록 강제하게 된다.
즉, 메서드 선언에 포함된 검사 예외 각각은 해당 메서드를 호출했을 때 발생할 수 있는 결과이므로 API 사용자에게 회복하라고 요구하는 것이다.
호출한 쪽에서 복구하리라 여겨지는 상황이라면 Checked Exception을 던져야 한다.
하지만, 복구 전략을 사용하여 복구할 수 있는 경우는 많지 않다.
만약, 유니크해야 하는 이메일 값이 중복되어 SQLException이 발생했다고 하자. 이 경우도 catch를 하여 Unchcked Exception을 발생 시켜 예외를 다시 전파하는 것이 현실적인 해결 방법이다.
프로그램에서 잡을 필요가 없거나 혹은 통상적으로 잡지 말아야 한다.
프로그램에서 해당 예외를 던졌다는 것은 복구가 불가능하거나 더 실행해봐야 득보다는 실이 많다는 뜻이다.
만약, 비검사 예외를 잡지 않은 스레드는 오류 메시지를 내뱉으며 중단된다.
클라이언트가 해당 API의 명세에 기록된 제약을 지키지 못했을 때는 런타임 예외를 발생시키자.(즉, 프로그래밍 오류)
ex) ArrayIndexOutOfBoundsException
배열의 인덱스는 0에서 배열 크기 -1 사이여야 한다.는 전제 조건이 지켜지지 않았다는 뜻이다.
public class Car {
private String name;
public Car(String name) {
if(name.length() > 5){
throw new IllegalArgumentException("이름은 5자를 넘을 수 없습니다.");
}
this.name = name;
}
}
예를 들어 자원 고갈이 말도 안 되는 크기의 배열을 할당해 생긴 프로그래밍 오류일 수도 있고, 지원이 일시적으로 부족한 것일수도 있다.(수요가 몰려서) 이 상황 같은 경우는 복구할 수 있는 상황이다.
따라서 해당 예외가 복구될 수 있는 것인지는 API 설계자의 판단에 달렸다.
복구 가능하다면 검사 예외를, 그렇지 않다면 런타임 예외를 던지자.
확신하기 어렵다면, 비검사 예외를 던지는게 나을 것이다.(아이템 71)
보통 JVM이 자원 부족 등 더 이상 수행을 할 수 없는 상황을 나타낸다.
특히나, Error 클래스를 상속해 하위 클래스를 만드는 일은 자제하자
즉, 우리가 구현하는 비검사 예외는 모두 RuntimeException의 하위 클래스여야 한다.
(AssertionError 제외)
검사 예외는 복구할 수 있는 조건일 때 발생한다.
따라서, 호출자가 예외 상황을 벗어나는데 필요한 메서드(접근자 메서드 - 아이템 75)를 제공해야 한다.
ex) 물건을 구입하는데, 잔고가 부족하다는 예외가 발생했다면,
잔고가 얼마나 부족하는지를 알려주는 접근자 메서드를 제공해야 한다.
- 복구할 수 있는 상황이라면 검사 예외를 사용하자.
- 프로그래밍 오류라면 비검사 예외를 사용하자
- 복구할 수 있는 상황인지 프로그래밍 오류인지 확실하지 않다면 비검사 예외를 던지자
- 검사 예외라면 예외를 벗어나는데 정보를 알려주는 접근자 메서드(아이템 75)도 같이 제공하자