[java] Throwable을 잡는 것이 나쁜 습관입니까?

잡는 것이 나쁜 습관 Throwable입니까?

예를 들면 다음과 같습니다.

try {
    // Some code
} catch(Throwable e) {
    // handle the exception
}

이것은 나쁜 습관입니까, 아니면 가능한 한 구체적이어야합니까?



답변

가능한 한 구체적이어야합니다. 그렇지 않으면 예상치 못한 버그가 이런 식으로 사라질 수 있습니다.

게다가, Throwable커버 Error도 마찬가지이며 일반적으로 반환 지점이 아닙니다 . 당신은 그것을 잡거나 다루고 싶지 않고, 당신은 당신의 프로그램이 즉시 죽어 올바르게 고칠 수 있기를 원합니다.


답변

이것은 나쁜 생각입니다. 사실, 잡는 Exception것 조차도 일반적으로 나쁜 생각입니다. 예를 들어 보겠습니다.

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
    inputNumber = 10; //Default, user did not enter valid number
}

이제 getUserInput ()이 잠시 차단되고 다른 스레드가 최악의 방법으로 스레드를 중지한다고 가정 해 보겠습니다 (thread.stop () 호출). catch 블록은 ThreadDeath오류 를 포착합니다 . 이것은 매우 나쁩니다. 해당 예외를 포착 한 후 코드의 동작은 거의 정의되지 않았습니다.

예외를 잡는 것과 비슷한 문제가 발생합니다. 아마도getUserInput() 때문에 InterruptException의 실패, 또는 결과, 또는 다른 실패의 모든 종류를 기록하는 동안 권한은 예외를 부인했다. 그 때문에 문제를 해결하는 방법도 모르기 때문에 무엇이 잘못되었는지 전혀 모릅니다.

세 가지 더 나은 옵션이 있습니다.

1-처리 방법을 알고있는 예외를 정확히 포착합니다.

try {
    inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
    inputNumber = 10; //Default, user did not enter valid number
}

2-발생하고 처리 방법을 모르는 예외를 다시 발생시킵니다.

try {
    doSomethingMysterious();
} catch(Exception e) {
    log.error("Oh man, something bad and mysterious happened",e);
    throw e;
}

3-finally 블록을 사용하면 다시 던지는 것을 기억할 필요가 없습니다.

 Resources r = null;
 try {
      r = allocateSomeResources();
      doSomething(r);
 } finally {
     if(r!=null) cleanUpResources(r);
 }


답변

또한을 잡을 때 특별한 치료가 필요한 Throwable잡을 수도 있습니다 InterruptedException. 자세한 내용 은 InterruptedException 처리 를 참조하십시오.

확인되지 않은 예외 만 포착하려는 경우이 패턴을 고려할 수도 있습니다.

try {
   ...
} catch (RuntimeException exception) {
  //do something
} catch (Error error) {
  //do something
}

이렇게하면 코드를 수정하고 확인 된 예외를 throw 할 수있는 메서드 호출을 추가 할 때 컴파일러가이를 상기시켜주고이 경우에 수행 할 작업을 결정할 수 있습니다.


답변

Error 클래스의 javadoc에서 직접 가져온 것입니다 (잡지 않는 것이 좋습니다).

 * An <code>Error</code> is a subclass of <code>Throwable</code>
 * that indicates serious problems that a reasonable application
 * should not try to catch. Most such errors are abnormal conditions.
 * The <code>ThreadDeath</code> error, though a "normal" condition,
 * is also a subclass of <code>Error</code> because most applications
 * should not try to catch it.

 * A method is not required to declare in its <code>throws</code>
 * clause any subclasses of <code>Error</code> that might be thrown
 * during the execution of the method but not caught, since these
 * errors are abnormal conditions that should never occur.
 *
 * @author  Frank Yellin
 * @version %I%, %G%
 * @see     java.lang.ThreadDeath
 * @since   JDK1.0


답변

메서드에서 예외 버블을 절대로 가질 수 없다면 나쁜 습관이 아닙니다.

정말 예외를 처리 할 수 ​​없다면 나쁜 습관입니다. 단순히 catch하고 다시 던지는 것보다 메소드 서명에 “throws”를 추가하는 것이 더 좋으며, 더 나쁜 것은 RuntimeException에 래핑하고 다시 던지는 것입니다.


답변

오류를 지나치게 많이 던지는 라이브러리를 사용하는 경우 Throwable 잡기가 필요할 때가 있습니다. 그렇지 않으면 라이브러리가 애플리케이션을 종료 할 수 있습니다.

그러나 이러한 상황에서는 모든 Throwables가 아니라 라이브러리에서 발생한 특정 오류 만 지정하는 것이 가장 좋습니다.


답변

Throwable은 throw 될 수있는 모든 클래스의 기본 클래스입니다 (예외뿐만 아니라). OutOfMemoryError 또는 KernelError를 포착하면 할 수있는 일이 거의 없습니다 ( java.lang.Error 를 포착하는 경우 참조 )

예외를 잡는 것으로 충분합니다.