프로그래밍 스티치

예외 되던지기(exception re-throwing) 본문

JAVA/예외처리

예외 되던지기(exception re-throwing)

프로그래밍 스티치 2022. 2. 11. 14:46
예외 되던지기(exception re-throwing)

한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇개는 try-catch문을 통해서 자체적으로 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써, 양쪽에서 나눠서 처리되도록 할 수 있다.

 

이것은 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 통해서 가능한데, 이것을 '예외 되던지기(exception re-throwing)'라고 한다.

 

이 방법은 하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 작업이 있을 때 사용된다. 이 때 주의할 점은 예외가 발생할 메서드에서는 try-catch문을 사용해서 예외처리를 해줌과 동시에 메서드의 선언부에 발생할 예외를 throws에 지정해줘야 한다는 것이다.

 

public static void main(String[] args) {
		try  {
			method1();		
		} catch (Exception e)	{
			System.out.println("main메서드에서 예외가 처리되었습니다.");
		}
	}	// main메서드의 끝

	static void method1() throws Exception {
		try {
			throw new Exception();
		} catch (Exception e) {
			System.out.println("method1메서드에서 예외가 처리되었습니다.");
			throw e;			// 다시 예외를 발생시킨다.
		}
	}	// method1메서드의 끝

 

 

위의 예시에서 알 수 있듯이 method1()과 main메서드 양쪽의 catch블럭이 모두 수행되었음을 알 수 있다. method1()의 catch블럭에서 예외를 처리하고도 throw문을 통해 다시 예외를 발생 시켰다. 그리고 이 예외를 main 메서드에서 한 번 더 처리한 것이다.

 

+주의할점!

반환값이 있는 return문의 경우, catch블럭에도 return문이 있어야 한다. 예외가 발생했을 경우에도 값을 반환해야하기 때문이다.

 

연결된 예외(chained exception)

한 예외가 다른 예외를 발생시킬 수도 있다. 예를 들어, 예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외(cause exception)'라고 한다. 예시를 살펴보자 

 

void install() throws InstallException
try{
	startInstall(); // SpaceException 발생
    copy();
} catch { SpaceException e) {
	InstallException ie = new InstallException("설치중 예외발생"); // 예외발생
    ie.initCause(e); // InstallException의 원인 예외를 SpaceException으로 지정
    throw ie; // InstallException을 발생시킨다.
} catch (MemoryException me) {
 '''

 

 

먼저 InstallException을 생성한 후에, initCause()로 SpaceException을 InstallException의 원인 예외로 등록한다. 그리고 'throw'로 이 예외를 던진다.

initCause()는 Exception클래스의 조상인 Throwable클래스에 정의되어 있기 때문에 모든 예외에서 사용 가능하다.

 

원인 예외에 관한 문법

Throwable initCause(Throwable cause) : w지정한 예외를 원인 예외로 등록

Throwable getCause() : 원인 예외를 반환

 

발생한 예외를 그냥 처리하면 될 텐데, 원인 예외로 등록해서 다시 예외를 발생시키는 이유는 무엇일까?

바로, 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해서이다.

 

또 다른 이유는, checked예외를 unchecked예외로 바꿀 수 있도록 하기 위해서이다. checked예외로 예외처리를 강제한 이유는 프로그래밍 경험이 적은 사람도 보다 견고한 프로그램을 작성할 수 있도록 유도하기 위함이었는데, 지금은 자바가 처음 개발되던 1990년대와 컴퓨터 환경이 많이 달라졌다. 그래서 checked예외가 발생해도 예외를 처리할 수 없는 상황이 하나둘 발생하기 시작했다. 이럴 때 할 수 있는 일이라곤 그저 의미없는 try-catch문을 추가한느 것 뿐인데, checked예외를 unchecked예외로 바꾸면 예외처리가 선택적이 되므로 억지로 예외처리를 하지 않아도 된다.

 

static void startInstall() throws SpaceException, MemoryException {
	if(!enoughSpace()) // 충분한 설치공간이 없다면!
    	throw new SpaceException("설치할 공간이 부족합니다") 
        
	if(!enoughMemory()) // 충분한 메모리가 없다면!
    	throw new MemoryException("t메모리가 부족합니다");
}

 

위의 예제는 checked예외의 예시인데 이것을 unchecked예외로 변경해보면 

 

static void startInstall() throws SpaceException {
	if(!enoughSpace()) // 충분한 설치공간이 없다면!
    	throw new SpaceException("설치할 공간이 부족합니다") 
        
	if(!enoughMemory()) // 충분한 메모리가 없다면!
    	throw new RuntimeException(new MemoryException("메모리가 부족합니다"));
} // 메모리 익셉션이 런타임익셉션의 원인 예외가 된것!

이렇게 MemoryException을 예외처리를 선택적으로 바꿀 수 있다! 이렇게 변경하면 선언부에 MemoryException을 선언하지 않아도 된다.

 

참고로 위의 코드에서는 initCause()대신 RuntimeException의 생성자를 사용했다

 

RuntimeException 생성자의 문법

RuntimeException(Thorwable cause) // 원인 예외를 등록하는 생성자

'JAVA > 예외처리' 카테고리의 다른 글

finally블럭  (0) 2022.02.09
메서드에 예외 선언하기  (0) 2022.02.08
예외 발생시키기  (0) 2022.02.08
멀티 catch 블럭  (0) 2022.02.08
try-catch문에서의 흐름  (0) 2022.02.08