핵심 요약
- 검사 예외는 API의 안전성을 향상시키는 도구로, 제대로 사용하면 유용하다.
- 그러나 남용 시 API 사용의 복잡성을 증가시킨다.
- 예외 상황에서 복구가 불가능하면 비검사 예외를 사용하고, 복구가 가능한 상황이면 옵셔널을 고려하자.
- 옵셔널로 충분한 정보를 제공할 수 없을 때에만 검사 예외를 사용해야 한다.
검사 예외의 단점
- API 사용자는 검사 예외 상황에 대해 대응할 수 있게 되어 프로그램의 안정성과 품질을 높일 수 있다.
- 그러나 API 사용자는 검사 예외를 반드시 처리해야 한다. 이는 코드의 복잡성을 증가시킨다.
- 또한, 스트림 연산 중간에서 검사 예외를 던지는 연산은 직접 사용할 수 없다.
- ex. map, filter같은 중간 연산에서 검사 예외를 던지는 메소드를 사용할 수 없다.
- 이로 인해, 검사 예외를 던지는 메소드의 사용성이 제한될 수 있으며, 이는 자바 8 이후 프로그래머에게 큰 부담이 될 수 있다.
검사 예외를 피하는 방법
1. Optional
- 메소드가 실패할 가능성이 있을 때, 실패의 원인이나 부가 정보 대신 빈 옵셔널 객체를 반환한다.
- 예외와 달리 부가 정보나 원인을 전달할 수 없다.
public class UserService {
public User findUserByIdChecked(int id) throws UserNotFoundException {
if (id <= 0) {
throw new UserNotFoundException("Invalid ID: " + id);
}
// 임의로 사용자 객체를 반환
return new User(id, "Alice");
}
}
class UserNotFoundException extends Exception {
public UserNotFoundException(String message) {
super(message);
}
}
UserService userService = new UserService();
try {
User user = userService.findUserByIdChecked(-1);
} catch (UserNotFoundException e) {
e.printStackTrace();
}
public class UserService {
public Optional<User> findUserByIdOptional(int id) {
if (id <= 0) {
return Optional.empty();
}
// 임의로 사용자 객체를 반환
return Optional.of(new User(id, "Alice"));
}
}
UserService userService = new UserService();
Optional<User> optionalUser = userService.findUserByIdOptional(-1);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
} else {
System.out.println("User not found.");
}
2. 상태 검사 메소드
- 검사 예외를 던지는 메소드를 2개로 쪼개 비검사 예외로 바꿀 수 있다
- 그러나 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인에 의해 상태가 변할 수 있다면 적절하지 않다.(item 69)
- 또한, 상태 검사 메소드와 동작 메소드가 중복 수행된다면 성능이 저하되니 적절하지 않다.
// 검사 예외를 던지는 메소드 - 리팩터링 전
try {
obj.action(args);
} catch (TheCheckedException e) {
// 예외 상황에 대처한다.
}
// 상태 검사 메소드와 비검사 예외를 던지는 메소드 - 리팩터링 후
if (obj.actionPermitted(args)) { // 상태 검사 메서드
obj.action(args);
} else {
// 예외 상황에 대처한다.
}
3. 단순 메소드 호출
- 기존 방식
try {
obj.action(args);
} catch (TheCheckedException e) {
// 예외 상황에 대처한다.
}
- 간단한 호출 방식
- action 메소드가 실패하지 않을 것이라는 확신이 있고, 실패 시 현재 스레드를 중단하길 원할 경우 적절하다.
- 코드가 간결하여 가독성과 유지보수성도 향상된다.
obj.action(args);
'Language > Java' 카테고리의 다른 글
[effective java] 아이템 73. 추상화 수준에 맞는 예외를 던지라. (0) | 2023.08.12 |
---|---|
[effective java] 아이템 72. 표준 예외를 사용하라. (0) | 2023.07.31 |
[effective java] 아이템 70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라. (0) | 2023.07.31 |
[effective java] 아이템 69. 예외는 진짜 예외 상황에만 사용하라. (0) | 2023.07.31 |
[effective java] 아이템 68. 일반적으로 통용되는 명명 규칙을 따르라. (0) | 2023.07.31 |