아이템 69. 예외는 진짜 예외 상황에만 사용하라
- 다음은 예외를 잘못 사용한 상황(배열의 끝을 감지하는데 예외를 사용)
try {
int i = 0;
while(true) range[i++].climb();
} catch (ArrayIndexOutOfBoundsException e) {}
- 예외는 오직 예외 상황에서만 사용해야함
- 일상적인 제어흐름으로 사용해서는 안됨
- 잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야함
아이템 70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
- 자바는 각 문제상황을 알리는 세가지 타입을 제공
- 검사 예외
- 런타임 예외
- 에러
- 호출하는 쪽에서 복구하리라 여거지는 상황이라면 검사 예외를 사용
- 프로그래밍 오류를 나타낼 때에는 런타임 예외를 사용
- 우리가 구현하는 비검사 throwable은 모두 RuntimeException의 하위 클래스여야함
아이템 71. 필요 없는 검사 예외 사용은 피하라
- 검사 예외를 제대로 사용하면 API와 프로그램의 질을 높일 수 있음
- 검사 예외를 던질 수 있다고 선언되면 사용자 측면에서는 catch 블록을 두거나 밖으로 예외를 던져야함
- API호출자가 예외 상황을 복구할 방법이 없다면 비검사 예외를 던저야함
- 복구 가능하다면 우선 옵셔널을 반환해도 될지 고민하고 옵셔널만으로는 상황을 처리하기에 충분한 정보를 제공할 수 없는 경우만 검사 예외를 사용해야함
아이템 72. 표준 예외를 사용하라
- 숙련된 프로그래머는 그렇지 못한 프로그래머보다 더 많은 코드를 재사용함
- 예외도 마찬가지이며 자바 라이브러리는 대부분 API에서 쓰기 충분한 수의 예외를 제공
- 표준 예외를 재사용하면 얻는게 많음
- 다른사람이 익히고 사용하기 쉬워짐
- 예외클래스 수가 적을 수록 메모리 사용량 및 클래스 적재 시간이 적게 걸림
널리 재사용되는 예외들
- IllegalArgumentException
- IllegalStateException
- NullPointerException
- IndexOutOfBoundsException
- ConcurrentModificationException
- UnsupportedOperationException
아이템 73. 추상화 수준에 맞는 예외를 던지라
- 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야함
- 그렇다고 해서 예외 번역을 남용하는것은 곤란
- 아래계층에서의 예외를 피할 수 없다면 적절한 로깅을 활용하면 좋음
아이템 74. 메서드가 던지는 모든 예외를 문서화하라
- 검사 예외는 항상 따로따로 선언
- 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화해야함
- 메서드가 던질 수 있는 예외를 각각 @throws 태그로 문서화하되, 비검사 예외는 메서드 선언의 throws목록에 넣지 말아야함
- 한 클래스에 정의된 많은 메서드가 같은 이유로 같은 예외를 던진다면 그 예외를 클래스 설명에 추가하는 방법도 존재
아이템 75. 예외의 상세 메시지에 실패 관련 정보를 담으라
- 예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 예외의 스택정보를 출력함
- 스택 추적은 예외 객체의 toString으로 보통은 예외 클래스 이름 뒤에 상세 메시지가 붙는 형태
- 실패 순산을 포착하려면 발생한 예외에 관려된 모든 매개변수와 필드의 값을 실패 메시지에 담아야함
아이템 76. 가능한 한 실패 원자적으로 만들라
- 호출한 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지해야함
- 이러한 특성을 실패 원자적(failure-atomic) 이라고함
- 메서드를 실패 원자적으로 만드는 방법은 다양함
- 불변 객체로 설계
- 매개변수 유효성 검사
- 실패할 가능성 있는 코드를 객체 상태를 바꾸는 코드보다 앞에 배치
- 임시 복사본에서 수행
아이템 77. 예외를 무시하지 말라
- catch 블록을 비워두면 예외가 무시됨, 이러면 예외가 존재할 이유가 없음
- 머릿속에서 사이렌을 울려야함
- 예외를 무시하기로 했다면 무시한 이유를 catch블록에 주석으로 작성해야함