📕🐘 도로락 - 코끼리를 냉장고에 넣는 방법
자바[Java] | 2017. 12. 12. 00:37

[JAVA] 자바 향상된 예외 처리 - Multi Catch문

참고글

멀티캐치

하나의 try 블록에서 여러개의 예외가 발생하는 경우 많은 catch 블럭이 발생하게 됩니다.

try{

}catch(예외1 e1){
    예외1 처리 로직
}catch(예외2 e2){
    예외2 처리 로직
}catch(예외3 e3){
    예외3 처리 로직
}

그러나 이렇게 많은 catch문이 발생하면 그 안에서 중복되는 코드들이 발생할 수 있습니다.

예를 들어 e.printStackTrace()를 통해 예외 정보를 출력하는 로직등이 대표적입니다.

JDK1.7 부터는 이러한 불편함을 해소하기 위해 멀티캐치(multi catch)문을 제공합니다.

멀티 캐치문은 다음과 같이 사용합니다. 하나의 catch 안에 | 논리연산의 or에 해당하는 기호를 사용하여 여러개의 예외를 연결할 수 있습니다.

try{

}catch(예외1 | 예외2 | 예외3 e){
   공통 예외로직 ex)e.printStackTrace();
}

멀티캐치 사용시 주의사항

멀티캐치는 상황에 따라 사용함으로써 간편하게 여러가지의 예외를 하나의 로직으로 처리할 수 있다는 장점이 있습니다. 그러나 그에 따른 제한사항 및 주의사항이 존재합니다.

1. Multi Catch문에 사용된 예외들은 예외의 상속관계에서 부모와 자식관계에 있으면 안됩니다.

다음의 경우에는 catch문에 ArithmeticExceptionRuntimeException을 동시에 처리하려 하고 있습니다.

try{

}catch (ArithmeticException | RuntimeException e) {

}
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    The exception ArithmeticException is already caught by the alternative RuntimeException

그러나 이대로 컴파일 하게되면 위와 같은 예외가 발생하게 되는데 그 이유는 다음과 같습니다.

ArithmeticExceptionRuntimeException의 자손 클래스이기 때문에 RuntimeException 하나만으로 처리가 가능하기 때문입니다.

컴파일러 입장에서는 불필요한 코드라고 판단했고 위 코드를 바람직하게 고친다면 다음과 같이 고칠 수 있을것입니다.

try{

}catch (RuntimeException e) {
    RuntimeException 하나로 하위 예외들을 모두 처리           
}

2. Multi Catch문에 사용된 예외들의 공통된 조상의 멤버만 사용할 수 있다.

여기서 멤버란 멤버메서드 및 멤버변수를 의미합니다. 이게 무슨뜻일까요? Multi Catch문에서는 하나의 참조변수로 예외를 처리한다는 사실을 깨달았을 것입니다.

catch(ExA | ExB | ExC e) // e라는 참조변수 하나로 처리

이러한 경우에 예외가 발생했을 때 e라는 참조변수가 가리키는 객체가 어느 예외 클래스의 인스턴스인지 알 수 없게 됩니다.

다음 코드에서는 예외가 발생했을 경우 ExA 예외의 메서드를 호출하게 되는데 만약 실제 발생한 예외가 ExB 였다면 해당 메서드가 존재하지 않을 수 있습니다.

try{
}catch(ExA | ExB | ExC e){
   e.methodA(); //e가 어느 예외인지 예측 불가능하므로 불가능한 코드
}

이러한 이유로 멀티캐치문에는 공통된 조상의 메서드만 호출하거나 정확히 어느 예외의 인스턴스인지 판단하여 캐스팅(형변환) 후 해당 메서드를 사용해야 합니다.

try{
}catch(ChildExA | ChildExB | ChildExC e){
   e.parentsMethod(); //공통조상인 parentsMethod()만 호출 가능
}

instanceof 연산을 통해 어느 예외의 인스턴스인지 판단 후 캐스팅해준 후 메서드를 사용합니다.

다만 이런 if문이 나타난다는 뜻은 예외별로 다른 처리가 필요하다는 뜻이므로 이런 경우에는 멀티캐치문이 아닌 평소대로 여러개의 캐치문을 사용하도록 하는것이 좋습니다.

try{
}catch(ChildExA | ChildExB | ChildExC e){
   if(e instanceof ChildExA){
       ChildExA a = (ChildExA)e; //캐스팅
       a.childMethodA();
   }else if(e instanceof ChildExB){
       ChildExB b = (ChildExB)e; //캐스팅
       b.childMethodB();
   }else{ ... }
}
도로락

도로락

Writer

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그