아이템 70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라. - ksw6169/effective-java GitHub Wiki
자바에서 제공하는 예외 타입
- 자바는 문제 상황을 알리는 타입(Throwable)으로 검사 예외, 런타임 예외, 에러를 제공한다.
검사 예외
- 검사 예외란 Exception 하위 클래스 중 RuntimeException을 상속하지 않은 예외를 말한다.
- 검사 예외를 던지면 호출자가 그 예외를 직접 처리하거나, 다른 메소드로 전달하도록 강제한다.
- 따라서 호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하라.
비검사 예외
- 비검사 예외는 런타임 예외와 에러로, 둘 다 동작 측면에서는 다르지 않다.
- 이 둘은 프로그램에서 잡을 필요가 없거나 혹은 통상적으로 잡지 말아야 한다.
- 프로그램에서 비검사 예외나 에러를 던졌다는 것은 복구가 불가능하거나 더 실행해봐야 득보다는 실이 많다는 뜻이기 때문이다.
런타임 예외
- 프로그래밍 오류를 나타낼 때는 런타임 예외를 사용하자.
- 런타임 예외의 대부분은 API의 명세에 기록된 전제 조건을 만족하지 못했을 때 발생한다.
- 예를 들어
ArrayIndexOutOfBoundsException
이 발생했다는 건 '배열의 인덱스는 0에서 -1 사이여야 한다' 는 전제 조건이 지켜지지 않았다는 뜻이다.
복구할 수 있는 상황인지 판단이 어렵다면 비검사 예외를 사용하라.
- 복구할 수 있는 상황인지 프로그래밍 오류인지는 항상 명확히 구분되지 않는다.
- 확신하기 어렵다면 아마도 비검사 예외를 선택하는 편이 나을 것이다.
에러
- JVM이 자원 부족, 불변식 깨짐 등 더 이상 수행을 계속할 수 없는 상황을 나타낼 때 사용한다.
- Error 클래스를 상속해 하위 클래스를 만드는 일은 자제하기 바란다. (업계에 널리 퍼진 규약)
- 다시 말해 직접 구현하는 비검사 Throwable은 모두 RuntimeException의 하위 클래스여야 한다.
- Error는 상속하지 말아야 할 뿐 아니라, throw 문으로 직접 던지는 일도 없어야 한다. (AssertionError는 예외다.)
Exception, RuntimeException, Error를 상속하지 않는 Throwable
- 암묵적으로 이러한 Throwable은 일반적인 검사 예외처럼 다룬다.
- 이런 Throwable은 정상적인 검사 예외보다 나을 게 하나도 없으면서 API 사용자를 헷갈리게 하므로 절대 사용해서는 안된다.
검사 예외라면 복구에 필요한 정보를 알려주는 메소드를 제공하라.
- 예외의 메소드는 주로 그 예외를 일으킨 상황에 관한 정보를 코드 형태로 전달하는 데 쓰인다.
- 이런 메소드가 없다면 직접 오류 메시지를 파싱해 정보를 빼내야 한다.
- Throwable 클래스들은 대부분 오류 메시지 포맷을 상세히 기술하지 않는다.
- 따라서 오류 메시지가 JVM이나 릴리스에 따라 포맷이 달라질 수 있기 때문에 오류 메시지를 파싱해 사용하는 코드는 깨지기 쉽고 다른 환경에서 동작하지 않을 수 있다.
- 그러므로 검사 예외를 사용하는 경우 예외 상황을 복구하기 위해 필요한 정보를 알려주는 메소드를 함께 제공하는 것을 고려하라.
핵심 정리
- 복구할 수 있는 상황이면 검사 예외를, 프로그래밍 오류라면 비검사 예외를 던지자.
- 확실하지 않다면 비검사 예외를 던지자.
- 검사 예외도 아니고 런타임 예외도 아닌 Throwable은 정의하지도 말자.
- 검사 예외라면 복구에 필요한 정보를 알려주는 메소드를 제공하라.
참고 자료