Java

[Java] 멀티 catch 블럭

Gemstone 2021. 7. 24. 02:08

JDK1.7 부터 여러 catch블럭을 '|' 기호를 이용해서, 하나의 catch 블럭으로 합칠 수 있게 되었으며, 이를

'멀티 catch블럭'이라고 한다. 아래의 코드에서 알 수 있듯이 '멀티 catch블럭'을 이용하면 중복된 코드를 줄일 수 있다.

그리고 '|' 기호로 연결할 수 있는 예외 클래스의 개수에는 제한이 없다.

 

※ 참고 → 멀티 catch 블럭에 사용되는 '|'는 논리 연산자가 아니라 기호이다. 

try {
	...
} catch (ExceptionA e) {
	e.printStackTrace();
} catch (ExceptionB e2) {
	e2.printStackTrace();
}

/* ↓↓↓↓↓↓ */

try {
	...
} catch (ExceptionA | ExceptionB e) {
	e.printStackTrace();
}

만일 멀티 catch블럭의 '|' 기호로 연결된 예외 클래스가 조상과 자손의 관계에 있다면 컴파일 에러가 발생한다.

try {
	...
} catch (ParentException | ChildException e) { // 에러!
	e.printStackTrace();
}

왜냐하면, 두 예외 클래스가 조상과 자손의 관계에 있다면, 그냥 다음과 같이 조상 클래스만 써주는 것과 똑같기 때문이다. 불필요한 코드는 제거하라는 의미에서 에러가 발생하는 것이다.

try {
	...
} catch (ParentException e) {
	e.printStackTrace();
}

그리고 멀티 catch는 하나의 catch블럭으로 여러 예외를 처리하는 것이기 때문에, 발생한 예외를 멀티 catch블럭으로 처리하게 되었을 때, 멀티 catch블럭 내에서는 실제로 어떤 예외가 발생한 것인지 알 수 없다. 그래서 참조변수 e로 멀티 catch블럭에 '|' 기호로 연결된 예외 클래스들의 공통 분모인 조상 예외 클래스에 선언된 멤버만 사용할 수 있다.

try {
	...
} catch (ExceptionA | ExceptionB e) {
	e.methodA(); // 에러. ExceptionA에 선언된 methodA()는 호출불가
    
    if(e instanceof ExceptionA) {
    	ExceptionA e1 = (ExceptionA)e;
        e1.methodA(); // OK. ExceptionA에 선언된 메서드 호출가능
    } else { // if(e instanceof ExceptionB)
    	...
    }
    
    e.printStackTrace();
}

필요하다면, 위와 같이 instanceof로 어떤 예외가 발생한 것인지 확인하고 개별적으로 처리할 수는 있다. 그러나 이렇게까지 해가면서 catch블럭을 합칠 일은 거의 없을 것이다. 마지막으로 멀티 catch블럭에 선언된 참조변수 e는 상수이므로 값을 변경할 수 없다는 제약이 있는데, 이것은 여러 catch블럭이 하나의 참조변수를 공유하기 때문에 생기는 제약으로 실제로 참조변수의 값을 바꿀 일은 없을 것이다.

여러 catch블럭을 멀티 catch블럭으로 합치는 경우는 대부분 코드를 간단히 하는 정도의 수준일 것이므로 이러한 제약에 대해 너무 고민하지 않아도 될 것 같다.