문제

잡는 것은 나쁜 습관인가? 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 오류를 잡습니다. 이것은 슈퍼 나쁜 것입니다. 그 예외를 잡은 후 코드의 동작은 크게 정의되지 않습니다.

비슷한 문제가 발생함에 따라 발생합니다. intertartexception 때문에 getUserInput()가 실패했거나 결과를 기록하려고하는 동안 사용 권한이 거부되었거나 모든 종류의 다른 오류를 기록합니다. 그게 무슨 일이 잘못되었는지 전혀 모르겠다. 그로 인해 문제를 해결하는 방법은 모른다.

세 가지 옵션이 있습니다.

1 - 처리 방법을 알고있는 예외를 정확히 잡으십시오 :

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

2 - Rethrow 당신이 실행하고 취급하는 방법을 모르는 예외 :

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

3 - 마지막으로 블록을 사용하여 Rethrow를 기억할 필요가 없습니다.

 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
}

이렇게 하면 코드를 수정하고 확인된 예외를 발생시킬 수 있는 메서드 호출을 추가할 때 컴파일러가 이를 알려 주고 사용자는 이 경우에 무엇을 할지 결정할 수 있습니다.

오류 클래스의 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
.

방법에서 예외 거품을 절대적으로 가질 수 없다면 나쁜 연습이 아닙니다.

실제로 예외를 처리 할 수 없다면 나쁜 연습입니다.메서드 서명에 단순히 붙잡고 다시 던지거나, 더 나쁜 것보다 "던지는 것"을 추가하는 것이 좋습니다.

오류를 던지는 라이브러리를 사용하는 라이브러리를 사용하는 경우 때로는 던지기가 필요합니다. 그렇지 않으면 라이브러리가 응용 프로그램을 죽일 수 있습니다.

그러나 이러한 상황에서는 모든 throwable 대신 라이브러리가 던져진 특정 오류 만 지정하는 것이 가장 좋습니다.

Throwable은 Throw되는 것보다 모든 클래스의 기본 클래스입니다 (예외뿐만 아니라).OutOfMemoryError 또는 KernelError를 ( Java를 catch-java-java-lang-error"> 참조 할 수있는 경우) 할 수있는 일이 거의 없습니다.lang.error? )

예외를 잡는 것이 충분해야합니다.

논리에 따라 다르므로 옵션 / 가능성에 더 구체적이어야합니다.의미있는 방식으로 반응 할 수있는 구체적인 예외가있는 경우 먼저 그것을 잡을 수 있고 그렇게 할 수 있습니다.

모든 예외 및 오류 (예 : 오류 메시지가있는 종료)에 대해 동일한 작업을 수행 할 수 있습니다.

일반적으로 첫 번째 경우는 던지기를 붙잡을 수 없게됩니다.그러나 아직도 잡기를 잡는 것이 얼마나 많은 경우가 있습니다.

이는 매우 나쁜 습관으로 설명되어 있지만 때로는 희귀한 유용할 뿐만 아니라 필수인 경우도 있습니다.다음은 두 가지 예입니다.

사용자에게 의미 있는 전체 오류 페이지를 표시해야 하는 웹 애플리케이션에서.이 코드는 큰 일이므로 이런 일이 발생하는지 확인합니다. try/catch 모든 요청 처리기(서블릿, 스트럿츠 작업 또는 모든 컨트롤러 ....) 주변

try{
     //run the code which handles user request.
   }catch(Throwable ex){
   LOG.error("Exception was thrown: {}", ex);
     //redirect request to a error page. 
 }

}

또 다른 예로, 자금 이체 비즈니스를 제공하는 서비스 클래스가 있다고 가정해 보겠습니다.이 메소드는 TransferReceipt 전송이 완료되었거나 NULL 그럴 수 없다면.

String FoundtransferService.doTransfer( fundtransferVO);

이제 이미징을 하면 List 사용자로부터 자금 이체를 수행하려면 위의 서비스를 사용해야 합니다.

for(FundTransferVO fundTransferVO : fundTransferVOList){
   FoundtransferService.doTransfer( foundtransferVO);
}

하지만 만약에 무슨 일이 일어날까요? 어느 예외가 발생합니까?한 번의 전송이 성공할 수도 있고 한 번의 전송이 성공하지 못할 수도 있으므로 중단해서는 안 됩니다. 모든 사용자를 통해 계속 진행해야 합니다. List, 각 전송에 대한 결과를 표시합니다.그래서 이 코드로 끝납니다.

for(FundTransferVO fundTransferVO : fundTransferVOList){
    FoundtransferService.doTransfer( foundtransferVO);
 }catch(Throwable ex){
    LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
  }
}

많은 오픈 소스 프로젝트를 탐색하여 throwable 실제로 캐시되고 처리됩니다.예를 들어 다음은 검색입니다. tomcat,struts2 그리고 primefaces:

https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable

질문은 약간 모호합니다. "Throwable를 잡는 것이 좋습니다."또는 "Throwable를 잡고 아무 것도하지 않아도됩니다."는 괜찮습니까? " 여기에 많은 사람들이 후자에게 답변했지만 그것은 부작용입니다. 99 %의 시간의 99 %를 "소비하지 말아야 할 때, 예외를 폐기하거나 Throwable 또는 IOException 또는 무엇이든지 폐기하십시오.

예외를 전파하면 답변 (많은 질문에 대한 답변과 같은 답변)은 "의존합니다"입니다. 그것은 예외로하고있는 것에 달려 있습니다. 왜 당신이 그것을 잡는지 당신이 왜 당신이 그것을 잡는지에 달려 있습니다.

Throwable를 잡으려고하는 이유의 좋은 예는 오류가있는 경우 일종의 정리를 제공하는 것입니다. 예를 들어 JDBC에서 트랜잭션 중에 오류가 발생하면 트랜잭션을 롤백하고 싶습니다.

try {
  …
} catch(final Throwable throwable) {
  connection.rollback();
  throw throwable;
}
.

예외는 삭제되지 않지만 전파됩니다.

그러나 일반적인 정책으로서, 당신이 이유가없고 너무 게으른 이유가 너무 게으른 이유가 없기 때문에, 이유가 없기 때문에, 나쁜 아이디어가 불량하고 나쁜 생각을 볼 수 있습니다.

일반적으로 Errors를 잡는 것을 피하고 싶지만 적어도 두 가지 특정 사례를 생각할 수 있습니다 :

  • 오류에 대한 응답으로 응용 프로그램을 종료하고, 특히 무해한 AssertionError입니다.
  • executorservice.submit () 사용자에게 예외를 다시 전달하여 처리 할 수 있습니다.

throwable 을 사용하면 오류 뿐만 아니라

를 다룹니다.

예제.

    public class ExceptionTest {
/**
 * @param args
 */
public static void m1() {
    int i = 10;
    int j = 0;
    try {
        int k = i / j;
        System.out.println(k);
    } catch (Throwable th) {
        th.printStackTrace();
    }
}

public static void main(String[] args) {
    m1();
}
.

}

출력 :

java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
.

Throwable은 모든 오류 및 규정의 수퍼 클래스입니다. catch 절에서 throwable을 사용하는 경우 모든 예외를 잡을뿐만 아니라 모든 오류도 catch합니다.응용 프로그램에서 처리하려는 심각한 문제를 나타내는 JVM에 의해 오류가 발생합니다.그것에 대한 전형적인 예는 OutOfMemoryError 또는 StackOverflowerROR입니다.둘 다 응용 프로그램의 제어 가외의 상황에 따라 발생하며 처리 할 수 없습니다.그래서 당신이 던지는 것이 예외적 인 것일 것이라고 확신하지 않는 한 당신은 꽤 확신하지 않아야합니다.

일반적으로 Throwable을 잡는 것은 나쁜 습관이지만(이 질문에 대한 수많은 답변에서 알 수 있듯이) Throwable 유용한 것은 매우 일반적입니다.제가 직장에서 사용하는 사례 중 하나를 간단한 예를 들어 설명하겠습니다.

두 개의 숫자를 추가하고 성공적으로 추가한 후 특정 사람들에게 이메일 알림을 보내는 방법을 생각해 보세요.반환된 숫자가 중요하고 호출 메서드에서 사용된다고 가정합니다.

public Integer addNumbers(Integer a, Integer b) {
    Integer c = a + b;          //This will throw a NullPointerException if either 
                                //a or b are set to a null value by the
                                //calling method
    successfulAdditionAlert(c);
    return c;
}

private void successfulAdditionAlert(Integer c) {
    try {
        //Code here to read configurations and send email alerts.
    } catch (Throwable e) {
        //Code to log any exception that occurs during email dispatch
    }
}

이메일 경고를 보내는 코드는 많은 시스템 구성을 읽으므로 해당 코드 블록에서 다양한 예외가 발생할 수 있습니다.그러나 우리는 경고 발송 중에 발생한 예외가 호출자 메서드에 전파되는 것을 원하지 않습니다. 해당 메서드는 단순히 제공하는 두 정수 값의 합에만 관련되기 때문입니다.따라서 이메일 경고를 발송하는 코드는 try-catch 블록, 어디에 Throwable 가 포착되고 모든 예외는 기록만 남으므로 나머지 흐름이 계속됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top