체님께서 리뷰를 진행하셨던 코드 중 이런 부분이 있었습니다.
...
} catch (CException e) {
throw e;
} catch (Throwable e) {
if ( e instanceof CException) {
CException e1 = (CException)e;
Object[] objErr = e1.getMessageArgs();
}
throw new CBizException("cu.fail.cuba0010_Control", new Object[]
{"Control 에러"}, e);
}
...
에서 if 절은 닿을 수 있는 코드 인가?? 하는 부분입니다. 여기에는 두 가지 문제가 들어있습니다.
1. e 가 CException 클래스의 객체라면 상위의 catch (CException)에 의해 잡히지 않나?
2. catch 절은 객체의 선언형(type)에 따르는가 또는 객체의 형(instanceof)에 따르는가? 다형성 문제
우선 예외에 대해서는 아래의 글을 참조해 주세요. 저도 정리가 정확히 되어 있지는 않아서리;;(http://
blog.ohmynews.com/icorea77/34761)
instanceof 는 생각보다 놀라운 것을 보여주네요. 부모-자식간의 관계일때 서로에 대한 항상 instanceof 는 참입
니다. 저는 자식 instanceof 부모 일때만 참일 것이라고 생각하고 있었는데 부모 instanceof 자식 또한 참입니
다. 형제간 이상의 먼 관계에 대해서는 거짓입니다.
다음으로 catch에 대한 문제입니다. 어쨋든 일단 CException은 Exception 클래스의 자식일 것입니다.
Throwable은 인터페이스라고 생각했는데 의외로 객체네요 ㅎㅎ able들은 모두 인터페이스라고 생각했는데 아닌가 봅니다.
Throwable은 예외 최상위 클래스로서 Exception과 Error 클래스의 부모입니다. 따라서 CException도
Throwable의 자식입니다.
제가 내린 결론부터 얘기 드리면 위의 if 절은 실행될 수 없다는 것입니다.
이러한 코드를 사용했습니다.
--------------------------------------------------
package testCatch;
public class TestException {
public static void main(String[] args) {
TestException test = new TestException();
test.testThrowable();
test.testCException();
test.testCSubException();
test.testNotCException();
test.testParentException();
}
void testThrowable() {
try {
throw new Throwable();
} catch (CException ex) {
System.out.println("testThrowable() catch (CException ex)");
} catch (Throwable ex) {
System.out.println("testThrowable() catch (Throwable ex)");
if (ex instanceof CException) {
System.out.println("This is untouchable!!!!");
}
}
}
void testCException() {
try {
throw new CException();
} catch (CException ex) {
System.out.println("testCException() catch (CException ex)");
} catch (Throwable ex) {
System.out.println("testCException() catch (Throwable ex)");
if (ex instanceof CException) {
System.out.println("This is untouchable!!!!");
}
}
}
void testCSubException() {
try {
throw new CSubException();
} catch (CException ex) {
System.out.println("testCSubException() catch (CException ex)");
} catch (Throwable ex) {
System.out.println("testCSubException() catch (Throwable ex)");
if (ex instanceof CException) {
System.out.println("This is untouchable!!!!");
}
}
}
void testNotCException() {
try {
throw (Throwable) new NotCException();
} catch (CException ex) {
System.out.println("testNotCException() catch (CException ex)");
} catch (Throwable ex) {
System.out.println("testNotCException() catch (Throwable ex)");
if (ex instanceof CException) {
System.out.println("This is untouchable!!!!");
}
}
}
void testParentException() {
try {
throw new ParentException();
} catch (CException ex) {
System.out.println("testParentException() catch (CException ex)");
} catch (Throwable ex) {
System.out.println("testParentException() catch (Throwable ex)");
if (ex instanceof CException) {
System.out.println("This is untouchable!!!!");
}
}
}
}
---------------------------------------------
객체의 관계는 아래와 같습니다.
Throwable
+ Exception
+ ParentException
+ CException
+ CSubException
+ NotCException
예외를 던지는 쪽에서 어떻게 하느냐에 따라 달라질 수 있지 않을까 하는 의구심을 버릴 수 없지만서도..
어렵네요 예외~~~
저도 테스트 완료!! ㅋㅋ
NewException1, Throwable 위치를 위아래 바꾸니 NewException1 catch 하는 곳에서
언리쳐블 코드라고 이클립스에서 빨간줄 뜨네요 ㅎㅎ
--------------------------------------------------------------
class ExceptionTest {
class NewException1 extends Exception {}
class NewException2 extends Exception {}
private void runTest() {
try {
// if (true) {
// throw new NewException2();
// }
if (true) {
throw new NewException1();
}
} catch (NewException1 ne) {
System.out.println("NewException 캐치");
} catch (Throwable te) {
System.out.println("Throwable 캐치");
if ( te instanceof NewException1) {
System.out.println("Throwable/NewException 캐치");
}
}
}
public static void main (String [] args) {
ExceptionTest exceptionTest = new ExceptionTest();
exceptionTest.runTest();
}
}
--------------------------------------------------------------
[출력]
NewException 캐치
--------------------------------------------------------------