본문 바로가기
JAVA/Java Study

[Java] throw와 throws는 언제 사용하는 것일까?

by ♡˖GYURI˖♡ 2024. 1. 9.

throw

자바에서 예외처리를 하면 throw와 throws 예약어를 자주 접하게 된다. throw는 아래처럼 사용된다.

 

throw의 경우 개발자가 의도적으로 예외를 발생시키는 것이다.

throw라는 키워드를 이용하여 주로 비즈니스 로직을 구현하는 과정 중 컴파일에는 문제가 없지만 해당 비즈니스 로직이 개발자가 의도한 대로 통과하지 못했을 경우, 고의로 예외를 발생시켜야 할 때 사용한다.

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

 

하지만 메서드 시그니처에 사용되는 throws는 어떤 곳에서는 사용되고, 또 어떤 곳에서는 사용되지 않는다. throws는 언제 사용하는 것일까?

 

 

throws

throws의 역할

public void queryDatabase() throws IOException {
    ...
}
  • throws는 메서드 시그니처의 일부로, 메서드를 호출하는 클라이언트에게 메서드의 동작 중 어떤 예외가 발생할 수도 있으므로 예외처리해주어야 한다는 것을 알려준다.
  • 접근제어자 반환타입 메서드명(인자) throws 예외1, 예외 2, ... → 여러 예외를 추가할 수도 있다.
  • 확인된 예외가 발생할 수 있을 경우 반드시 throws로 추가해주어야 하고, 미확인 예외의 경우 추가할 수는 있으나 추가하지 않는 것이 권장된다.

throws의 경우, 메서드 내에서 예외처리를 하지 않고 해당 메서드를 사용한 곳에서 예외 처리를 하도록 예외를 위로 던지는 것이다. ( = 예외의 전가)

public class Test {
	public static void main(String[] args) {
		int a = 2;
		int b = 0;
		try {
			divide(a,b);
		} catch (ArithmeticException e) {
			e.printStackTrace();
		}

	}

	public static int divide(int a, int b) throws ArithmeticException {
		if (b == 0) {
			throw new ArithmeticException("0으로 나눌 수 없습니다.");
		}
		return a / b;
	}
}

 

예시를 보면 divide 메서드는 예외를 자신이 처리하지 않고 throws 키워드를 통해 자신을 호출한 main 메서드에게 책임을 전가했다.

 

여기까지 정리하자면 throw는 강제로 예외를 발생시키는 것이며 개발자의 판단에 따른 처리가 가능하다.

throws는 자신을 호출한 메서드에게 책임을 전가하여 호출한 메서드에서 예외처리를 하도록 강요한다.

 

throw를 사용하는 이유 : 예외가 발생할 수 있는 코드가 있다는 것을 인지시키고 예외 처리를 강요하며, 여러가지 발생 가능한 예외들을 호출한 메서드에서 한 번에 처리할 수 있게 하여 관리를 용이하게 해 줄 수 있다.

 

 

 

확인된 예외 vs 미확인 예외

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

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

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

만약 클라이언트가 예외로부터 회복할 수 없다면, 미확인 예외로 한다.

 

 

확인된 예외와 미확인 예외의 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를 시그니쳐에 작성하지 않고, 확인된 예외를 메소드 내에서 처리하지도 않을 경우 컴파일 에러가 발생한다.

 

 

 

 

 


 

 

throws는 언제 사용해야할까?

throws란 뭘까?

velog.io

 

Dev Day

스타트업에 도전하는 주니어 개발자의 개발 이야기

day0404.tistory.com