Item71. 필요 없는 검사 예외 사용은 피하라!
검사 예외
- 결과를 코드로 반환하거나 비검사 예외를 던지는 것과 달리, 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다.
- 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다.
- 검사 예외를 던질 수 있다고 선언됐으면, 호출 시 catch 블록을 두어 예외를 처리하거나 더 바깥으로 전파해야만 하기 때문이다.
- 또, 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없다.
- API를 제대로 사용한다면 발생하지 않는 예외이거나, 프로그래머가 예외에 대한 조치를 취하는 것에 유의미한 의미가 없는 경우라면 비검사 예외를 사용하는 게 좋다.
- 검사 예외를 여러 개 던져야 하는 상황이라면 어쩔 수 없이 예외 처리를 하겠지만, 단 하나의 검사 예외를 던지는 경우라면 그 하나 때문에 catch 블록을 사용해야 하고, 스트림에서 직접 사용하지 못하는 문제도 발생하니 검사 예외를 안 던지는 방법이 있는지 고민해보자.
검사 예외를 회피하는 방법
적절한 결과 타입을 담은 옵셔널을 반환하는 것이다.
- 검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환하면 된다.
- 이 방식은 예외 발생 이유를 알려줄 수 없다는 단점이 존재한다. (예외를 사용한다면 구체적인 예외 타입, 그 타입이 제공하는 메서드를 활용해 부가 정보를 제공하는 것도 가능하다.)
검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 바꾸는 방식이다.
- 이 방식에서 첫 번째 메서드는 예외가 던져질지 여부를 boolean 값으로 반환한다.
1 2 3 4 5
try { obj.action(args); } catch (TheCheckedException e) { ... // 예외 상황에 대처한다. }
- 리팩터링 전 코드다.
1 2 3 4 5
if(obj.actionPermitted(args)){ obj.action(args); } else { ... // 예외 상황에 대처한다. }
- 리팩터링 후의 코드다.
- 프로그래머가 이 메서드가 성공하리라는 걸 안다거나, 실패 시 스레드를 중단하길 원한다면 이처럼 사용해도 된다.
- actionPermitted는 상태 검사 메서드에 해당하므로, 외부 동기화 없이 여러 스레드가 동시 접근 가능하거나 외부 요인에 의해 상태가 변할 수 있다면, 이 방법은 적절치 못하다. actionPermitted와 action 호출 사이에 객체 상태가 변할 수도 있기 때문이다. (아이템 69 참조)
핵심 정리
- 꼭 필요한 곳에서만 사용한다면 검사 예외는 프로그램의 안전성을 높여준다.
- 남용한다면 고통스러운 API를 낳는다.
- API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자.
- 복구 가능하고, 호출자가 그 처리를 하길 원한다면, 우선 옵셔널 반환을 고민하자.
- 옵셔널만으로 상황 처리에 충분한 정보를 제공할 수 없다면 검사 예외를 던지자.
Comments powered by Disqus.