본문은 Effective Java를 읽고 간단하게 정리한 글입니다. 필요에 따라 생략/수정된 부분이 있을 수 있으며, 내용이 추후 변경될 수 있습니다.
선결론
- 검사 예외는 프로그램의 안정성을 높일 수 있지만, 남용한다면 API를 쓰기 어렵게 만들 수 있다
- API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자
- 복구가 가능하고 호출자가 그 처리를 해주길 바란다면 우선 옵셔널을 반환해도 될지 고민한 후, 옵셔널만으로 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지자
검사 예외의 문제
- 호출하는 코드에서 catch 블록을 두어 처리하거나 throw를 통해 더 바깥으로 던져 문제를 전파해야만 한다
- API 클라이언트측에 부담을 준다
- throw를 통해 바깥으로 던질 경우 API의 유연성이 떨어진다(의존성이 생김)
- 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없다
검사 예외를 사용하는 경우
- API를 제대로 사용해도 발생할 수 있는 예외(IOException, SQLException)
- 프로그래머가 의미 있는 조치를 취할 수 있는 경우
- 위의 두 조건에 해당하지 않는 경우엔 비검사 예외를 사용하는 게 좋다
검사 예외를 피하는 방법
1) 적절한 결과 타입을 담은 옵셔널을 반환하기
- 예외가 발생한 이유를 알려주는 부가 정보를 담을 수 없다
- 예외를 사용하면 구체적인 예외 타입과 그 타입이 제공하는 메서드들을 활용해 부가 정보를 제공할 수 있다(아이템 70)
2) 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 전환하기
검사 예외를 던지는 메서드 - 리팩터링 전
public class Item71 {
public static void main(String[] args) {
MyObject obj = new MyObject();
try {
obj.action(args);
} catch (TheCheckedException e) {
... // 예외 상황에 대처한다.
}
}
static class TheCheckedException extends Exception {
}
static class MyObject {
public void action(String[] args) throws TheCheckedException {
throw new TheCheckedException();
}
}
}
상태 검사 메서드와 비검사 예외를 던지는 메서드 - 리팩터링 후
public class Item71 {
public static void main(String[] args) {
MyObject obj = new MyObject();
if (obj.actionPermitted(args)) {
obj.action(args);
} else {
... // 예외 상황에 대처한다.
}
}
static class TheUncheckedException extends RuntimeException {
}
static class MyObject {
public void action(String[] args) {
throw new TheUncheckedException();
}
public boolean actionPermitted(String[] args) {
... // 상태 검사 로직을 수행한다.
return false;
}
}
}
- 아이템 69를 참고하여 위와 같은 리팩토링 방식이 적절한지 점검하자
- 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인에 의해 상태가 변할 수 있다면 이 방법은 적절하지 않다
- 상태 검사 메서드와 상태 의존적 메서드 호출 사이에 객체의 상태가 변할 수 있기 때문이다
- 성능이 중요한 상황에서 상태 검사 메서드(actionPermitted)가 상태 의존적 메서드(action)의 작업을 일부 수행한다면 이 방법은 적절하지 않다
예외 처리 X
public class Item71 {
public static void main(String[] args) {
MyObject obj = new MyObject();
obj.action(args); // 비검사 예외를 던진다
}
... // 생략
}
- 이 메서드가 성공하리라는 걸 알거나, 실패 시 스레드를 중단하길 원한다면 다음과 같이 메서드 내에서 별도의 예외처리를 하지 않는 방법을 선택할 수 있다
'책 > Effective Java' 카테고리의 다른 글
[이펙티브 자바] 아이템 80: 스레드보다는 실행자, 태스크, 스트림을 애용하라 (0) | 2022.07.21 |
---|---|
[이펙티브 자바] 아이템 72: 표준 예외를 사용하라 (0) | 2022.07.16 |
[이펙티브 자바] 아이템 70: 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라 (0) | 2022.07.15 |
[이펙티브 자바] 아이템 69: 예외는 진짜 예외 상황에만 사용하라 (0) | 2022.07.15 |
[이펙티브 자바] 아이템 68: 일반적으로 통용되는 명명 규칙을 따르라 (0) | 2022.07.15 |