검사 예외를 제대로 활용하면 API와 프로그램의 질을 높일 수 있다.
결과를 코드로 반환하거나 비검사 예외를 던지는 것과 달리, 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다.
검사 예외의 과한 사용
검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다.
- 어떤 메서드가 검사 예외를 던질 수 있다고 선언됐다면, 이를 호출하는 코드에서는 catch 블록을 두어 그 예외를 붙잡아 처리하거나 더 바깥으로 던져 문제를 전파해야만 한다.
- 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없다.
API를 제대로 사용해도 발생할 수 있는 예외이거나, 프로그래머가 의미 있는 조치를 취할 수 있는 경우에 검사 예외를 사용하고, 둘 다 아니면 비검사 예외를 사용하자
아래와 같은 검사 예외는 쓰지말자
AssertionError를 던지는 것으로 예외를 처리
try {
// 예외 발생 가능한 코드
} catch (TheCheckedException e) {
throw new AssertionError();
}
- 예외를 처리하는 대신에 또 다른 예외를 던져 프로그램의 실행을 중단시킨다.
- 특별한 이유 없이 예외를 무시하거나 가려버리는 것이므로 권장되지 않는다.
예외의 스택 트레이스 출력 후 종료
try {
// 예외 발생 가능한 코드
} catch (TheCheckedException e) {
e.printStackTrace();
System.exit(1);
}
- 상세한 정보를 출력하고 프로그램을 종료시킨다.
검사 예외를 우회하는 방법
- 메서드가 단 하나의 검사 예외를 던진다면 프로그래머가 지는 부담이 크다
- 이미 다른 검사 예외도 던지는 상황이었다면 또 다른 검사 예외를 추가하는 catch문을 추가하면 끝이다.
- 예외가 단 하나라면 새로 try 블록을 추가해야 하고, 스트림에서 직접 사용하지 못하게 된다.
- 검사 예외를 안 던지는 방법을 고민해보자.
1. 옵셔널 반환
- 검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환
- 예외가 발생한 이유를 알려주는 부가 정보를 담을 수 없다.
2. 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 변환
- 첫 번째 메서드를 예외가 던져질지 여부를 boolean 값으로 반환한다.
검사 예외를 던지는 메서드 - 리팩터링 전
try {
obj.action(args);
} catch (TheCheckedException e) {
// ...예외 상황에 대처한다.
}
상태 검사 메서드와 비검사 예외를 던지는 메서드 - 리팩터링 후
if (obj.actionPermitted(args)){
obj.action(args);
} else{
// ...예외 상황에 대처한다.
}
- 리팩터링 후의 API가 더 아름답진 않지만 유연하다.
- 아래와 같은 이유로 해당 리팩터링이 적절하지 않을 수 있다.
- actionPermitted가 action 메서드의 작업 일부를 중복 수행한다면 성능에서 손해이다.
- actionPermitted는 상태 검사 메서드에 해당하므로 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인에 의해 상태가 변할 수 있다. (actionPermitted와 action 호출 사이에 객체의 상태가 변할 수 있기 때문에)
결론
- 꼭 필요한 곳에만 사용한다면 검사 예외는 프로그램의 안전성을 높여준다.
- 남용하면 고통스러운 API가 만들어진다.
- API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자.
- 복구가 가능하고 호출자가 그 처리를 해주길 바란다면 우선 옵셔널을 반환해도 될지 고민해 보자.
- 옵셔널만으로 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지자.
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] Item 73. 추상화 수준에 맞는 예외를 던지라 (0) | 2023.08.11 |
---|---|
[Effective Java] Item 72. 표준 예외를 사용하라 (0) | 2023.08.06 |
[Effective Java] Item 70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라 (0) | 2023.08.05 |
[Effective Java] Item 69. 예외는 진짜 예외 상황에만 사용하라 (0) | 2023.08.05 |
[Effective Java] Item 68. 일반적으로 통용되는 명명 규칙을 따르라 (0) | 2023.08.04 |