체크 예외 재정의에 대하여.

Walter Mitty·2025년 4월 10일
0

개인공부

목록 보기
51/51

Runnable 인터페이스를 활용한 클래스에서 Override한 메서드 run()에서 스레드에 sleep() 메서드를 사용할 때 우리는 늘 try~catch를 해왔다.

run() 메서드를 구현할 때 InterruptedException 체크 예외를 밖으로 던질 수 없는 걸까?

이 부분은 Java에서 메서드를 재정의할 때, 재정의 메서드가 지켜야할 예외와 관련된 규칙이 있기 때문.

  • 체크 예외
    • 부모 메서드가 체크 예외를 던지지 않는 경우, 재정의된 자식 메서드도 체크 예외를 던질 수 없다.
    • 자식 메서드는 부모 메서드가 던질 수 있는 체크 예외의 하위 타입만 던질 수 있다.
  • 언체크(런타임) 예외)
    • 예외 처리를 강제하지 않으므로 상관없이 던질 수 있다.

자주 쓰던 코드 👇

static class SongThread implements Runnable {
	
    @Override
    public void run() {
    	// slee(1000); 이거 바로 안되고
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
		}
    }
}

공부하면서 Runnable 인터페이스의 run() 메서드를 오버라이드해서 사용했다. 따라서 내가 사용했던 run() 메서드의 부모 메서드는 Runnable 인터페이스의 run()!!
부모 메서드인 러너블의 런 메서드를 보면 따로 체크 예외를 던지고 있지 않다.

@FunctionalInterface
public interface Runnable {
    /**
     * Runs this operation.
     */
    void run();
}

알다시피 InterruptedExceptionException 클래스의 자식이다.
그런데 부모인 Runnalbe 인터페이스의 run() 메서드가 체크 예외 처리를 안하고 있는데
자식인 SongThread의 run() 메서드가 아래 처럼 체크 예외를 던질 수 있을까?
당연히 불가능!

@Override
public void run() throws InterruptedException {
	Thread.sleep(1000);
}

왜 이런식으로 처리하냐면
부모 클래스의 메서드를 호출하는 코드는 부모 메서드가 던지는 특정 예외만을 처리하도록 작성되는데, 자식 클래스가 더 넓은 범위의 예외를 던지게 되면 해당 코드는 모든 예외를 제대로 처리하지 못하고 예상치 못한 런타임 오류를 초래하거나 예외 처리의 일관성을 해칠 수 있다.

만약 예외 처리가 적절히 처리되지 않거나 일관성을 해쳐서 프로그램이 비정상 종료되는 상황이 있다...? 끔-찍!!!!!
하지만 체크 예외를 강제하는 이런 부분들은 자바 초창기 기조고 최근엔 체크 예외보다는 언체크(런타임) 예외를 선호한다고 한다!

따라서 따로 ThreadUtils 추상 클래스를 만들어 해당 클래스에서 예외처리를 전부 해두고, 다른 곳에서 ThreadUtils를 불러서 쓰는게 좋다.

0개의 댓글