2010-06-02 3 views
15

다른 예외로 중첩 된 예외를 catch하고 싶습니다.다른 예외로 중첩 된 예외 catch

} catch (RemoteAccessException e) { 
      if (e != null && e.getCause() != null && e.getCause().getCause() != null) { 
      MyException etrp = (MyException) e.getCause().getCause(); 
      ... 
      } else { 
      throw new IllegalStateException("Error at calling service 'service'"); 
      } 
     } 

이보다 효율적이고 우아한 할 수있는 방법이 있나요 : 나는 현재이 방법을하고 있어요?

답변

19

은 중첩 된 예외를 "잡기"선택적으로 더 우아한 방법이 없습니다. 이런 종류의 중첩 된 예외를 많이 잡는다면 코드를 일반적인 유틸리티 메서드로 리팩토링 할 수 있습니다. 그러나 여전히 우아하거나 효율적이지는 않습니다.

우아한 해결책은 예외 중첩을 제거하는 것입니다. 첫 번째 장소에서 예외를 연결하거나 중첩 된 예외를 스택에서 더 위쪽으로 (선택적으로) 풀고 재발행하지 마십시오.

예외가 3 개 이유로 중첩되는 경향이있다 : 당신은 원래 예외의 세부 사항은 응용 프로그램의 오류 복구에 유용 ... 될 가능성 것을 결정했다

  1. 하지만 당신은 그들을 유지하려면 진단 목적.

  2. 확인 된 예외를 허용하지 않지만 귀하의 코드 (어쩔 수없이)가 그러한 예외를 throw하는 API 메소드를 구현하고 있습니다. (일반적인 해결 방법은 체크되지 않은 예외의 내부 예외를 "밀수"하는 것입니다.)

  3. 당신은 당신의 방법에 체크 된 예외의 필요를 많이 피하기 위해 게으른과 하나의 예외에 관련되지 않은 예외의 다양한 세트를 돌리고있다

    서명 . 첫 번째 경우에

, 당신은 당신의 초기 가정/디자인이 잘못 랩 예외 차별해야하고, 당신이 둥지를 제거 할 수 있도록 이상적인 솔루션이 변경 메소드 서명 인 경우.

두 번째 경우에는 컨트롤이 문제가있는 API 메서드를 통과하자마자 예외를 래핑해야합니다.

세 번째 경우에는 예외 처리 전략을 재고해야합니다. 즉 올바르게 처리하십시오.


1 - 7.

+0

세 번째 이유는 (IOException처럼) 던져 질 수있는 예외 유형의보다 일반적인 수퍼 클래스를 던짐으로써 해결할 수 있습니다. 이것은 유사하고 그룹화 될 수있는 많은 예외 유형 인 경우에만 해당됩니다. – Marc

+0

@ 마르크 - 어떤 경우에만 "작동"합니다. 예외의 공통 상위 유형이 '예외'인 경우 *를 선언하면 정말 나쁜 생각입니다. 게다가 코드 독독성과 개별 예외를 선언 할 유지 가능성의 관점에서 볼 때 * 자주 * 더 좋습니다. 또는 적어도, 요점까지. 어느 쪽이든 포장은 케이스 # 3 "문제"를위한 게으른 해결책이다. –

0

의심 스럽지만 예외 유형이 올바른 경우 instanceof으로 확인할 수 있습니다.

편집 : 중첩 예외가 래핑 된 이유가 있어야하므로 중첩 된 예외를 잡는 목적이 무엇인지 스스로 자문해야합니다.

12

e.getCause().getCause()이 실제로 MyException인지 확인해야합니다. 그렇지 않으면이 코드는 ClassCastException이됩니다. 아마 이런를 작성합니다 : 당신은 예외 처리가 효율적이고 우아 할 이유

} catch(RemoteAccessException e) { 
    if(e.getCause() != null && e.getCause().getCause() instanceof MyException) { 
     MyException ex = (MyException)e.getCause().getCause(); 
     // Do further useful stuff 
    } else { 
     throw new IllegalStateException("..."); 
    } 
} 
+5

e.getCause에 대한 검사() getCause() = null이 필요하지 않습니다 N이 null의 경우의 instance false를 반환하기 때문에이 경우!. –

2

내가 효과적인 정착, 이유를 볼 수 없습니다. 이유 때문에 예외라고합니다.

이 코드는 유지 관리의 악몽이 될 것입니다. 관심이있는 예외를 던지기 위해 호출 스택을 재 설계 할 수 없습니까? 중요하다면 메소드 시그너처는 그것을 보여 주어야하고 2 개의 다른 예외에 싸여 숨기지 않아야합니다.

처음 (e! = null)은 필요하지 않습니다.

그리고 당신은 e.getCause MyException instanceof를(). getCause())에 3 더 나은 변경할 수 있습니다

+1

* "왜 예외 처리가 효율적이고 우아 해지기를 바라는 이유는 없습니다 ..."- 정말요? 정말? (물론 그런 일은 일어나지 않을 것입니다. 그러나 그 일이 일어나기를 원하지 않을 이유는 없습니다.) –

+0

:-) 알지만, 하루의 시간은 제한적일뿐입니다. 효율적이고 우아한 휴식. 내 말은 Java Exception handling을 우아하게하는 것은 발레를 코뿔소로 가르치려는 것과 같다. 그리고 던지는 예외는 아주 느리다, 그래서 결코 능률적이지 않을 것이다. 그래서 나는 효과가 있다고 생각합니다. –

+0

지원 엔지니어에게 가장 큰 불만은 예외 처리 코드의 버그입니다. 상황에 대한 관련 정보를 캡처해야하지만 아직 까다로운 문제입니다 (이 코드 샘플에서는 예외가 있습니다). 그것은 (그리고 흔적도없이) 죽지 않는다. – rwong

9

ExceptionUtils#getRootCause() 방법 올 수있는 사실은,이 작업을 수행하는 반 합법적 인 이유 중 하나 때문에 자바에서 다중 예외 캐치 구문의 도입에 사라진 그러한 상황에서 매우 편리합니다. 당신은 다음과 같이 할 수

+0

여기가 최고의 대답입니다. 신사 숙녀 여러분 – TolkienWASP

0

:.

catch (RemoteAccessException e) { 
    int index = ExceptionUtils.indexOfThrowable(e, MyExcetption.class) 
    if (index != -1) { 
     //handleMyException 
    } else { 
    } 
} 
관련 문제