Exception의 계층구조와 Throwable
Java의 Exception에 대한 계층구조는 대략 다음과 같습니다.
Throwable
+ Error
+ Exception
+RuntimeException
+NullPointerException 등등
+RuntimeExcpetion 외의 Exception (IOException 등등)
Throwable은 예외처리를 할 수 있는 최상위 클래스가 됩니다. (java.lang.Object.finalize()의 경우 protected void finalize() throws Throwable 로 정의되어있습니다.)
Throwable은 stack에 대한 정보를 관리할 수 있습니다. Exception이 떴을 때, 어느 코드의 몇 번째 줄에서 발생했고 어디서 호출되었는지 stack 정보들이 뜨는 것을 보신 적이 있지요? 이런 것들은 전부 Throwable에서 처리가 되는 것입니다. (참고: Throwable을 이용한 디버그 코드 예제 )
Throwable의 주요 멤버는 2가지가 있습니다.(내부적으로 생성해서 쓰는 멤버말고.)
첫 번째는 발생원인을 기술할 수 있는 String이고, 두번째는 발생원인인 Throwable입니다. 그래서 Throwable의 생성자는 인자를 안 받는 것, String만 받는 것, Throwable만 받는 것, 둘 다 받는 것 등 총 4가집니다
발생원인을 담고 있는 String의 경우 발생한 구체적인 상황을 저장하는 용도로 쓰입니다. 왜 Exception이 발생되었는가에 대한 정보를 String으로 만들어서 저장할 수 있습니다.
원인을 나타내는 Throwable은 원래 Excpetion에 대한 정보를 간직하게 됩니다.
예를 들어, GenericServlet의 doService()의 선언부를 보겠습니다.
protected void doService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
서블릿을 실행하다가 디비 접속에 실패했다고 칩시다. 이런 경우 SQLException을 던져야 할 것 같은데, 메쏘드 선언부에는 SQLException을 던질 수 없게 되어있습니다. 그럴 경우 SQLException을 ServletException에 담아서 던지면 됩니다. ServletException 같은 경우는 좀 더 추상화된 Exception이고, SQLException은 실제 Exception에 대한 정보를 담고 있는 Exception이 됩니다. 즉, 구체적인 케이스를 담고 있는 Exception을 추상화된 Exception에 담아 추상화된 Exception에 대해서 예외 처리를 하면 됩니다. 이렇게 Exception이 다른 Exception을 가지는 것을 Exception chain이라 합니다.
Exception chain을 만드는 방법은 두가지가 있는데, 첫번째는 생성자를 이용하는 방법입니다. 코드는 아래와 같습니다.
try{
|
두번째는 Throwable의 initCause()를 쓰는 방법입니다.
try{
|
initCause(Throwable)은 최종적으로 return this; 가 호출이 됩니다. 즉, 리턴 타입이 Throwable입니다.
딱 봐도 첫번째 방법이 훨씬 쉬워보입니다. 그러나, exception chain이 java 1.4 이후에 도입된 방식입니다. 따라서 그 이전에 작성된 Exception 중에는 Throwable을 인자로 받는 생성자를 지원하지 않는 경우가 많습니다. 제일 흔하게 쓰는 Exception 중 하나인 IOException 만 해도 Throwable을 인자로 받는 생성자는 존재하지 않습니다. (생성자는 상속되지 않는다는 점을 다시 상기하세요.) 따라서, 첫번째 방식은 쓸 수 없는 경우가 꽤 있습니다.
exception chain의 컨셉은 Wrapping 또는 캐스팅입니다. ServletException으로 변화될 수 없는 SQLException을 ServletException으로 담아서 넘기는 것이지요. Adapter 패턴을 생각하시면 됩니다.
이것을 호출하는 쪽 코드를 살펴 보지요.
try {
} catch(ServletException e){
|
Exception chain을 만든 방식이 위에서 얘기한 첫번째인지 두번째인지는 상관 없이 Throwable.getCause()를 호출하면 원래의 Exception을 가져올 수 있습니다.
참조[펌] : http://iilii.egloos.com/4709173
'Java > The Java Language' 카테고리의 다른 글
생성자가 private으로 선언된 경우/의미 (0) | 2014.03.25 |
---|---|
Text Encoding (0) | 2013.10.12 |
Java Dynamic Proxy --> Draft (0) | 2013.02.07 |
The Class Class and Reflection (0) | 2013.02.07 |
What is Enum in Java (1) | 2013.02.06 |