예외는 오직 예외 상황에서만 사용하고 절대로 일상적인 제어 흐름용으로 쓰이면 안된다.
잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없어야 한다.
호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하자
프로그래밍 오류를 나타낼 때는 런타임 예외를 사용하자
구현하는 비검사 throwable은 모두 RumtimeException의 하위 클래스 여야 한다.
검사 예외도 아니고 런타임 예외도 아닌 throwable은 사용하지 말자
꼭 필요한 곳에서만 사용한다면 검사 예외는 프로그램의 안정성을 높여 주지만, 남용하면 쓰기 고통스러운 API를 만든다.
API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지는것이 좋다.
복구가 가능하고 호출자가 그 처리를 해주길 바란다면, 우선 Optional 반환해도 될지 고민하고 Optional만으로는 상황을 처리하기 충분한 정보를 제공 할수 없을때만 검사 예외로 던지자
Exception, RuntimeException, Throwable, Error는 직접 재사용하지 말자
사용법
IllegalArgumentException : 허용하지 않는 값이 인수로 건너젔을때 (null 은 nullPotinerExceotion)
IllegalStateException : 객체가 메소드를 수행하기에 적절하지 않는 상태 일때
NullPointerException : null을 허용하지 않는 메소드에 null을 건넸을때
IndexOutOfBoundsException : 인덱스가 범위를 넘어 섰을때
ConcurrentModificationException : 허용하지 않는 동시 수정이 발견됬을때
UnsupportOperationException : 호출한 메서드를 지원하지 않을때
상황에 부합한다면 항상 표준 예외를 재사용하는 것이 좋다.
상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야한다.
아래 계층의 예외를 예방하거나 스스로 처리할 수 없고, 그 예외를 상위 계층에 그대로 노출하기 곤란하다면 예외 번역을 사용하자
이때 예외 연쇄를 이용하면 상위 계층에는 맥락에 어울리는 고수준 예외를 던지면서 근본 원인도 함께 알려주어 오류를 분석하기에 좋다 (아이템 75)
메소드가 던질 가능성이 있는 모든 예외를 문서화 해라
문서화엥는 javadoc의 @throws 태그를 사용하면 된다.
검사 예외만 메서드 선언의 throws 문에 일일이 선언하고, 비검사 예외는 메소드 선언에는 기입하지 맣ㄹ자
발생 가능한 예외를 문서로 남겨놓지 않으면 다른 사람이 그 클래스나 인터페이스를 효과적으로 사용하기 어렵거나 심지어 불가능할수 있다.
실패 순간을 포착하려면 발생한 예외에 관여한 모든 매개변수와 필값을 실패 메세지에 담아야 한다.
사후 분석을 위해 실패 순간의 상황을 정확하게 포착해 예외에 상세히 적는 것이 좋다. (추적할수 있는 정보 제외)
try-catch 문에서 catch블록을 비워두면 예외가 존재할 이유가 없어진다.
예외를 무시하기로 했다면 catch안에 그 이유를 주석으로 남겨놓고 예외 변수의 이름도 ignored로 바꿔놓도록 하자