메소드 재정의(오버라이딩)만으로 예외 처리를 변경할 수 있을까?
결론부터 말하면 가능합니다. 자바에서는 부모 클래스의 메소드를 재정의(오버라이드)할 때, 메소드 로직 전체를 바꾸지 않고도 예외 처리 방식만 변경하는 것이 허용됩니다. 다만, 이 경우 반드시 지켜야 할 세 가지 규칙이 있습니다.
규칙 1. 비검사 예외(Unchecked Exception)는 자유롭게 던질 수 있다
재정의하는 메소드는 부모 메소드가 예외를 던지는지 여부와 상관없이 비검사 예외(RuntimeException 및 그 하위 클래스)를 얼마든지 던질 수 있습니다. NullPointerException, ArithmeticException 등이 대표적인 예이며, 이러한 예외는 메소드 시그니처에 선언하지 않아도 되기 때문에 제약이 없습니다.
규칙 2. 새로운 검사 예외(Checked Exception)나 더 넓은 범위의 검사 예외는 던질 수 없다
재정의하는 메소드는 부모 메소드가 선언하지 않은 새로운 검사 예외를 던지거나, 부모 메소드가 선언한 예외보다 더 넓은(broader) 범위의 검사 예외를 던져서는 안 됩니다. 이를 위반하면 컴파일 오류가 발생합니다. 이는 다형성(polymorphism) 환경에서 호출자가 부모 타입 기준으로 예외를 처리하기 때문입니다.
규칙 3. 더 좁거나 더 적은 수의 예외는 던질 수 있다
반대로, 재정의하는 메소드는 부모 메소드가 선언한 예외보다 더 좁은(narrower) 범위의 하위 예외를 던지거나, 아예 예외를 던지지 않는 것도 허용됩니다. 즉, 예외 범위를 줄이는 방향은 항상 안전합니다.
예제 코드
import java.io.IOException;
class Parent {
void display() throws Exception {
System.out.println("부모 클래스 메소드");
}
}
class Child extends Parent {
// 부모(Exception)보다 좁은 IOException을 던지므로 유효함
@Override
void display() throws IOException {
System.out.println("자식 클래스 메소드");
}
}
위 예제에서 자식 클래스는 부모가 선언한 Exception보다 좁은 범위인 IOException을 던지므로 문제없이 컴파일됩니다. 그러나 자식이 SQLException처럼 상속 관계가 없는 새로운 검사 예외를 던지려 한다면 컴파일 오류가 발생합니다.
핵심 요약
- 비검사 예외(RuntimeException 계열): 조건 없이 자유롭게 추가 가능
- 검사 예외(Checked Exception): 새로 추가하거나 더 넓게 확장하는 것은 불가
- 예외 범위 축소 또는 생략: 항상 허용됨
이 규칙들을 기억해 두면 오버라이딩 시 발생하는 컴파일 오류를 사전에 예방하고, 보다 안정적인 예외 처리 설계를 할 수 있습니다.