5

이 질문에는 이미 답변이 있습니다.

일부 레거시 코드에서 오버런 예외가 잡히고 다시 던져지는 것을 보았습니다. 이것은 좋은 연습입니까? 그렇다throw e;동일한 예외를 재발행하거나 새 예외를 만들 수 있습니까?

catch (Exception e) {
        StringBuilder sb = new StringBuilder(
                            "Oops. Something went wrong with id: ");
        sb.append(id);
        sb.append(". Exception is: ");
        sb.append(e.toString());
        System.out.println(sb.toString());
        throw e;
}


  • 예외를 계속 전달하려면 잡기와 다시 던지기가 좋습니다. 코드가 그것을 잡아서 로깅 한 다음 다시 던지면 이상하게 보입니다. - Andrew

5 답변


2

throw e동일한 예외를 다시 제기하고 있습니다. 최소한 원래 스택 추적을 유지합니다. 일어난 일에 대한 정보를 기록한 stdout에 메시지를 쓰는 것만으로 원래의 예외가 진행되도록합니다.

중대한 장소는 아니며 중앙 지점에 예외를 기록하고 스택 트레이스를 기록하기에 충분해야합니다. 더 많은 정보를 추가해야하는 경우 (예제에서 ID를 기록하는 위치) 새 예외에서 원래의 예외를 원인으로 중첩 한 다음 새 예외를 throw하는 것이 좋습니다. 아마도 중앙 집중식 로깅이 없거나 예외가 어딘가에서 먹는 경향이있는 상황에서 발생했을 것입니다.


  • 어디에도 아무것도 로깅하지 않는다고 생각합니다. 잡힌 예외가 표시되는지 확인하고 클라이언트가 중앙 위치에서 예외 로깅을 제안한 것처럼 측정을 수행하여 클라이언트가 원하는대로 적절하게 처리하도록 요청합니다. - Prateek
  • @Prateek : 로깅에 의해 나는 stdout에 글을 쓰는 것을 의미했습니다 (매우 원유이지만 일종의 로깅입니다). 지금 다시 말 했어요. - Nathan Hughes
  • 좋아,하지만 그걸로rethrowing다른 클라이언트가 이러한 예외를 다르게 처리하려고 시도 할 수 있으므로 예외가 실제로 좋을 수 있습니다. 동의하지 않습니까? - Prateek
  • @Prateek : 안에 중첩 된 오래된 예외를 던지면 내 선호하는 방법이 될 것입니다. 그런 식으로 새로운 예외가 더 많은 정보를 추가 할 수 있고 예외 유형이 다를 수 있습니다. - Nathan Hughes
  • 그래, 그게 내가 갈 것이지만이 하나도 나쁘지 않아 :) - Prateek

1

이것은 대개 나쁜 습관입니다.catch(Exception e)(때때로포켓몬 예외 처리언제너 모두 잡을거야.) 잡기...마다단일 예외. 이러한 예외 처리는 다음과 같은 이유로 거의 유용하지 않습니다.

  • 그것은 런타임 예외도 잡는다.
  • 던져진 예외 유형에 대한 정보를 잃게됩니다.
  • 반응을 보이거나 처리 할 수 없습니다.특유한예외.

지금 서명 방법입니다.public void whatever() throws Exception, 이는 거의 유용하지 않습니다. 이제 사슬을 따라 올라가는 모든 것이 어떤 종류의 예외를 던지는지 전혀 알 수 없습니다. 그들은해야 할 것이다.instanceof특정 예외를 포착하는 목적을 완전히 무효로하는 수표

두 번째 예외 사항에 관한 한,throw e;같은 예외 객체를 던집니다. 예외를 래핑하고 싶다면 새 예외를 만들 수 있습니다. 즉, 다음과 같은 작업을 수행 할 수 있습니다.throw new MyCustomException(e);. 또한 메소드 서명을 변경해야합니다.

더 이상 사슬의 위로 아무것도 없다면, 나는 이것이 나쁘지는 않다는 것을 짐작할 수 있습니다 (그래도 여전히 크지는 않습니다). 그것은 던져진 모든 예외를 기록하려고 시도하는 메서드처럼 보입니다. 그러나, 다시, 이것을하는 더 나은 방법이 있습니다.


1

내 최선의 추측은 보호의 두 계층을 가지고 노력하는 것입니다. 오류 메시지가 표시되는지 확인하고 클라이언트가 원하는대로 예외를 처리하도록 요청하십시오.catch절은 예외로부터 복구하기 위해 아무 것도하지 않습니다.

나는 그것을 좋거나 나쁜 습관으로 생각하지 않을 것이다. 요구 사항에 따라 API를 사용하는 100 개의 다른 클라이언트가있는 것처럼 어느 쪽이든 이동하는 것을 고려할 수 있으며 각각의 클라이언트는 서로 다른 방법으로 복구 할 수 있습니다.exception. 무엇이 잘못되었는지를 표시함으로써 클라이언트가 클라이언트를 처리하는 방법을 결정하는 레이어 바로 아래에 기본 액션 레이어를 추가합니다.exception.

이제 질문으로 돌아가십시오. 나는 생각한다.throw e같은 예외 객체를 던집니다. 예외는 다음과 같습니다.objects자바에서 당신은new exception object할 수 있기 전에throw그것은 내가 당신의 코드에서 일어나는 것을 볼 수 없습니다.


  • 자바로 새로운 예외를 던져야한다고 주장하고 싶습니까? - pamphlet
  • @pamphlet 요점은 예외 클래스 (또는 확장 클래스)의 객체를 만들어야하는 사용자 정의 된 예외를 던져야한다는 것입니다.throw그것. 위의 코드에서 객체가 아닌 다른 객체를 생성하는 예외는 없습니다.e - Prateek

0

throw e동일한 예외가 발생합니다. 이 일을하는 이유가 있었을 지 모르지만 그렇게 할 이유가 있습니다. 예제 코드에서는 다음에 메시지가 전송됩니다.System.out, 나중에 스택 추적이 인쇄 된 경우System.err, 그것은 syncronized되지 않을 것이며, 실제로 두 사람이 귀하의 콘솔에 짜여진 수 있습니다.

보다 나은 접근 방법은 다음과 같습니다.

catch (Exception e) {
    StringBuilder sb = new StringBuilder(
                        "Oops. Something went wrong with id: ");
    sb.append(id);
    sb.append(". Exception is: ");
    sb.append(e.toString());
    throw new Exception(sb.toString(), e); // The original exception is an argument
}

이렇게하면 새로운Exception수정 된 메시지와 함께Exception디버깅에 도움이되는 스택 추적에.


  • 또 다른 옵션은 적절한 로깅 메커니즘을 사용하는 것입니다. - pamphlet

0

그것은 좋은 연습 일 수 있습니다. 나는 항상 변환을 사용한다고 생각합니다.RuntimeException초 동안. 필요하다면 더 나은 예외 처리로 변경할 수 있습니다. 이 목적을 위해 구아바에 유틸리티 클래스가 있습니다.쓰레기이것은 예외 전파를 만든다.

귀하의 경우에는 예외가 있어야하지만런타임 예외로 변환왜냐하면 일반적인 것을 던지는 메소드를 선언했기 때문입니다.Exceptionthrow하는 메소드와 똑같습니다.RuntimeException전화하는 사람에게. 첫 번째 경우에는 '모든 것을 잡다', 후자에서는'아무것도 잡는다.'. 아직 실제 응용 프로그램에서이 두 가지의 차이점을 경험하지 못했습니다. 그래서 나는 더 좋아한다.RuntimeException그들은 타이핑이 덜 필요하기 때문에.

매력 있는 것Exception

  • 확인 된 예외 (IO 예외, 보안 오류, 동시성 등)
  • 런타임 예외 (아무것도, 예기치 않은 쓰레기, 아래 참조)
  • 모두- 이들은 모든 오류의 99 %입니다 (Error그러나 왼쪽)

매력 있는 것RuntimeException

  • null 포인터 예외, 범위를 벗어난 예외 인덱스, 예외 액세스, 예외를 전파하는 + APIRuntimeException- 이것은또한 많이

내 요점은 당신이Exception당신은이 모든 경우를 정말로 다룰 수 없습니다. 따라서 전화를 걸면 더 적은 타이핑을하는 것 외에는 아무런 차이가 없습니다.RuntimeException.


  • 일반 투척Exception던지기와 같지 않다.RuntimeException. 전자가 검사되므로 메소드 서명에서 언급해야합니다. 하위 클래스 인 모든 예외Exception그러나아니의 하위 클래스RuntimeException확인 된 예외입니다. - Vivin Paliath
  • 그래, 맞아. 나는 그것이 발신자에게 아무런 차이가 없다는 것을 의미합니다. 일반 잡기Exception& # 39; 모든 것을 포착 함 & quot;을 의미합니다. 매력 있는 것RuntimeException'무엇이든 잡는 중'을 의미합니다. 나는 아직 두 가지 경우의 실제 차이를 보지 못했습니다. - Andrey Chaschev
  • 그것의지발신자에게 차이를 만들어라. 메소드가 던지고있는 경우Exception호출자는 메서드를 처리하거나 다시 throw해야하지만 호출자는 메서드가 throw되고있는 경우 호출을 수행하지 않아도됩니다.RuntimeException. 또한 잡기RuntimeException'무엇이든 잡는 중'을 의미하지 않습니다. 그것서브 클래스 인 그러한 예외를 캐치합니다.RuntimeException(과RuntimeException그 자체); 확인 된 예외는 발견되지 않습니다. - Vivin Paliath
  • 네, 논리적 인 차이가 있습니다. 나는 아직 그것을 사용하고 있지 않다. 대부분의 경우 일반Exception자바의 나쁜 습관이기 때문에 현실 세계의 예를 생각하기가 정말 어려울 것입니다. 전파RuntimeException그러나 반 패턴이 될 수는 없으며 좋은 연습이 될 수 있습니다. - Andrey Chaschev

연결된 질문


관련된 질문

최근 질문