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{
    // 디비 관련 로직


}catch(SQLException e){
    throw new ServletException(e);
}

 

 

두번째는 Throwable initCause() 쓰는 방법입니다

 

try{
    // 디비 관련 로직


}catch(SQLException e){
    throw (ServletException) new ServletException().initCause(e);
}

 

 

initCause(Throwable) 최종적으로 return this; 호출이 됩니다. , 리턴 타입이 Throwable입니다.

봐도 첫번째 방법이 훨씬 쉬워보입니다. 그러나, exception chain java 1.4 이후에 도입된 방식입니다. 따라서 이전에 작성된 Exception 중에는 Throwable 인자로 받는 생성자를 지원하지 않는 경우가 많습니다. 제일 흔하게 쓰는 Exception 하나인 IOException 해도 Throwable 인자로 받는 생성자는 존재하지 않습니다. (생성자는 상속되지 않는다는 점을 다시 상기하세요.) 따라서, 첫번째 방식은 없는 경우가 있습니다
.

exception chain
컨셉은 Wrapping 또는 캐스팅입니다. ServletException으로 변화될 없는 SQLException ServletException으로 담아서 넘기는 것이지요. Adapter 패턴 생각하시면 됩니다.

이것을 호출하는 코드를 살펴 보지요.

 

try {
    
someSevlet.doService(req, res);

 

} catch(ServletException e){
    Throwable cause = e.getCause();     // Exception chain으로 호출되지 않았을 경우 null
    if(cause instanceof SQLException ){ // cause !=null은 체크하지 않아도 됨. null일 경우 instanceof는 false를 리턴.
        // 디비에러에 대해 처리하는 로직.
    } else{
        // 뭔가 다른 처리
    }
} catch(IOException 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
Posted by Steven J.S Min
,