throws는 언제 사용해야할까?

이상민·2021년 10월 6일
1
post-thumbnail

1. throw

자바에서 예외처리를 하면 throwthrows 예약어를 자주 접하게 된다. throw는 아래처럼 사용하는 것을 많이 봤을 것이다. "throw 뒤에 오는 Exception 객체로 예외를 발생시키는구나"하고 그 역할을 추론할 수 있다. 하지만 메소드 시그니쳐에 사용되는 throws 어떤 곳에서는 사용되고 또 어떤 곳에서는 사용되지 않는다. 언제 사용하는 것일까?

public void validate(String name) {
    if (name.isBlank())
        throw new IllegalArgumentException();
}

2. throws

2-1. throws의 역할

public void queryDatabase() throws IOException {
    ...
}
  • throws는 메소드 시그니쳐의 일부로, 메소드를 호출하는 클라이언트에게 메소드의 동작 중 어떤 예외가 발생할 수도 있으므로 예외 처리해줘야한다는 것을 알려준다

  • 접근_제어자 반환_타입 메소드명(인자) throws 예외1, 예외2, ... 형태로 여러 예외를 추가할 수도 있다

  • 확인된 예외가 발생할 수 있을 경우 반드시 throws로 추가해줘야하고 미확인 예외의 경우 추가할 수는 있으나 추가하지 않는게 권장된다.

2-2. 확인된 예외 vs 미확인 예외

  • 자바의 예외는 크게 확인된 예외미확인 예외로 나눌 수 있다

    • 확인된 예외 :
      프로그램의 제어 밖에 있는 예외들. 컴파일 시점에 예외처리 여부를 확인한다
      모든 RuntimeException상속하지 않는 예외
      ex) FileNotFoundException, SQLException

    • 미확인 예외 :
      프로그램 로직의 오류로인한 예외들. 런타임 시점에 예외처리 여부를 확인한다
      모든 RuntimeException상속하는 예외
      ex) ArrayIndexOutOfBoundsException, IllegalArgumentException

만약 클라이언트가 예외로부터 회복하는 것을 어느정도 기대할 수 있다면, 확인된 예외로 한다. 만약 클라이언트가 예외로부터 회복할 수 없다면, 미확인 예외로 한다.

오라클의 자바 문서는 어떤 예외를 사용할지에 대해 위와 같이 기술한다. 회복을 기대한다는 것이 애매하게 느껴진다. 이 부분에 대해서는 나중에 더 자세히 찾아봐야겠다.

2-3. 확인된 예외와 미확인 예외의 throws

public class CheckedExceptionTest {
    public static void main(String[] args) {
        throwsCheckedTest();  // 확인된 예외를 발생하나 코드에서 예외처리를 하지 않아 컴파일에 실패한다 
    }

    static void throwsCheckedTest() throws Exception {
        throw new Exception("확인된 예외 throws 테스트");
    }
}

// 실행 결과
>> java: unreported exception java.lang.Exception; must be caught or declared to be thrown



public class UncheckedExceptionTest {
    public static void main(String[] args) {
        throwsUncheckedTest();  // 예외처리를 하지 않아도 컴파일된다. 실행시 RuntimeException 발생
    }

    static void throwsUncheckedTest() throws RuntimeException {
        throw new RuntimeException("미확인 예외 throws 테스트");
    }
}

// 실행 결과
>> Exception in thread "main" java.lang.RuntimeException: 미확인 예외 throws 테스트
	at Main.throwsUncheckedTest(Main.java:9)
	at Main.main(Main.java:3)

위의 코드와 결과에서 볼 수 있듯이 미확인 예외는 throws에 추가 가능하지만 예외처리가 강요되지 않기 때문에 메소드 시그니처를 통해 정보를 전달하는 것 이외에 역할은 하지 못한다. 반면 확인된 예외는 throws를 통해 콜 스택의 다른 메소드에게 예외처리를 넘길 수 있다. throws를 시그니쳐에 작성하지 않고, 확인된 예외를 메소드 내에서 처리하지도 않을 경우 컴파일 에러가 발생한다.

profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

0개의 댓글