[Effective Java] 아이템 71 : 필요 없는 검사 예외 사용은 피하라
0. 들어가며
저를 포함한 많은 자바 개발자들은 Checked Exception이 try-catch 구문이나 throw 를 강제하기 때문에 좋아하지 않는데요.
그래서 요즘은 거의 Checked Exception은 사용하지 않고, 불가피하게 사용하게 되는경우는 RuntimeException으로 변환해서 다루는 경우도 많은 것 같습니다.
게다가 Checked Exception을 던지는 메서드는 Stream에서 직접 사용할 수 없어서 더욱 기피하게되는데요.
하지만 이런 Checked Exception도 제대로 활용한다면 API와 프로그램의 질을 올릴 수 있다고 합니다.
1. 제대로 활용할 수 있는 경우
Checked Exception을 제대로 활용할 수 있는 경우는 다음과 같습니다.
- 외부에서 API를 정상적으로 호출해도 발생할 수 있는 경우
- 제어할 수 없는 상황에서 오류가 발생할 수 있는 경우
- 개발자가 의미있는 조치를 취할 수 있는 경우
public void printFile(String filePath) {
File file = new File(filePath);
try (FileReader fr = new FileReader(file))
{
int content;
while ((content = fr.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
printFile("Effective-java.txt");
위 예시는 텍스트를 읽어와 출력하는 메서드인데요.
프로그램 로직상으로는 아무런 문제가 없지만, 제어할 수 없는 상황(파일시스템)에 의해 예외가 발생합니다.
이런 경우에는 Checked Exception이 유용하게 사용될 수 있습니다.
그리고 예외가 발생한 경우 개발자가 의미있게 조치를 취할수도 있는데요.
public void printFile(String filePath) throw IOException {
File file = new File(filePath);
FileReader fr = new FileReader(file);
int content;
while ((content = fr.read()) != -1) {
System.out.print((char) content);
}
}
try
{
printFile("Effective-java.txt");
} catch (IOException e) {
System.out.print("해당 파일을 찾을 수 없습니다");
}
위와 같은 경우 예외가 발생하면, 다른 흐름으로 유도하도록 Checked Exception을 활용할 수 있습니다.
2. 사용을 피해야 하는 경우
위에서 설명한 상황이 아니라면 왠만하면 피하는게 좋습니다.
무언가 반환해야하는 상황이라면 Optional을 이용하는것이 좋습니다.
public Result getSomething() throw IOException {
// select query
if (result == null) {
return Optional.empty();
}
return Optional.of(result);
}
Result result = getSomething().orElseThrow(() -> new RuntimeException());
위 처럼 예외가 호출하는쪽에 충분한 정보를 제공할 수 있다면, Optional을 사용하는게 좋습니다.
왜냐하면 1번에서 잠시 본 것 처럼, Checked Exception을 사용하면 호출하는쪽에서 처리하는것이 번거로울 수 있기 때문입니다.
그런데 만약 정상적인 흐름으로 갈 수 없고, 여기서 중단되어야 한다면 다음과 같이 Unchecked Exception을 던지는 것을 고려하는게 더 좋습니다.
public void printFile(String filePath) {
File file = new File(filePath);
try (FileReader fr = new FileReader(file)) {
int content;
while ((content = fr.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
throw new RuntimeException(e)
}
}
printFile("Effective-java.txt");