Frage

Ist es eine schlechte Praxis zu fangen Throwable?

Zum Beispiel so etwas:

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

Ist das eine schlechte Praxis oder sollten wir so genau wie möglich sein?

War es hilfreich?

Lösung

Sie müssen so spezifisch wie möglich sein.Ansonsten könnten unvorhergesehene Fehler auf diese Weise entriegeln.

außerdem Throwable deckt generakodicetagcode sowie das ist Normalerweise keinen Renditepunkt .Sie möchten das nicht fangen, dass Ihr Programm sofort sterben soll, damit Sie es richtig beheben können.

Andere Tipps

Das ist eine schlechte Idee.In der Tat sogar fangen Exception ist normalerweise eine schlechte Idee.Betrachten wir ein Beispiel:

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

Nehmen wir nun an, dass getUserInput() für eine Weile blockiert und ein anderer Thread Ihren Thread auf die schlechteste Weise stoppt (er ruft thread auf.anhalten() ).Ihr Fangblock wird einen fangen ThreadDeath Fehlermeldung.Das ist super schlecht.Das Verhalten Ihres Codes nach dem Abfangen dieser Ausnahme ist weitgehend undefiniert.

Ein ähnliches Problem tritt beim Abfangen von Ausnahmen auf.Vielleicht getUserInput() fehler aufgrund einer InterruptException oder einer Ausnahme mit verweigerter Berechtigung beim Versuch, die Ergebnisse zu protokollieren, oder allerlei anderer Fehler.Sie haben keine Ahnung, was schief gelaufen ist, da Sie aus diesem Grund auch keine Ahnung haben, wie Sie das Problem beheben können.

Sie haben drei bessere Möglichkeiten:

1 - Fangen Sie genau die Ausnahme (n) ab, mit denen Sie umgehen können:

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

2 - Wiederholen Sie jede Ausnahme, auf die Sie stoßen und die Sie nicht handhaben können:

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

3 - Verwenden Sie einen finally Block, damit Sie nicht daran denken müssen, erneut zu werfen:

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

Beachten Sie auch, dass, wenn Sie fangen Throwable, Sie können auch fangen InterruptedException was eine besondere Behandlung erfordert.Sehen Umgang mit InterruptedException für weitere Details.

Wenn Sie nur ungeprüfte Ausnahmen abfangen möchten, können Sie auch dieses Muster berücksichtigen

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

Auf diese Weise erinnert Sie der Compiler daran, wenn Sie Ihren Code ändern und einen Methodenaufruf hinzufügen, der eine überprüfte Ausnahme auslösen kann, und Sie können dann entscheiden, was in diesem Fall zu tun ist.

direkt vom Javadoc der Fehlerklasse (der empfiehlt, diese nicht zu fangen):

generasacodicetagpre.

Es ist keine schlechte Praxis, wenn Sie keine Ausnahmeblase aus einer Methode haben können.

Es ist eine schlechte Praxis, wenn Sie nicht mit der Ausnahme nicht umgehen können.Besser, um die Methode-Signatur "Würfeln" hinzuzufügen, als nur zu fangen und wieder zu werfen oder, schlimmer, in einer RuntimeeException einzuwickeln und wieder zu werfen.

Fangwinde ist manchmal notwendig, wenn Sie Bibliotheken verwenden, die fehlerhafte Fehlböden verwenden, andernfalls töten Ihre Bibliothek Ihre Bewerbung.

Es wäre jedoch am besten unter diesen Umständen, nur die von der Bibliothek geworfenen spezifischen Fehler anzugeben, und nicht alle Wurfablässe.

Wurfbar ist die Basisklasse für alle Klassen, als (nicht nur Ausnahmen) geworfen werden kann.Es gibt wenig, wenn Sie einen OutofMemoryError oder KernelError fangen (siehe , wenn Sie Java fangen.lang.error? )

Ausnahmen fangen, sollte ausreichen.

Es hängt von Ihrer Logik ab oder um spezifischer für Ihre Optionen / Möglichkeiten zu sein.Wenn es eine bestimmte Ausnahme gibt, dass Sie möglicherweise auf sinnvolle Weise weiter reagieren können, könnten Sie es zuerst fangen und dies tun.

Wenn es nicht gibt, und Sie sind sicher, dass Sie für alle Ausnahmen und Fehler dasselbe tun, (z. B. mit einer Fehlermeldung), als es nicht das Problem ist, das Wurf zu fangen.

In der Regel gilt der erste Fall und Sie würden das Wurf nicht fangen.Aber es gibt immer noch viele Fälle, in denen es fangen, es fein macht.

Obwohl es als sehr schlechte Praxis beschrieben wird, können Sie manchmal feststellen selten fälle, in denen es nicht nur nützlich, sondern auch obligatorisch ist.Hier sind zwei Beispiele.

In einer Webanwendung, in der Sie dem Benutzer eine bedeutungsvolle vollständige Fehlerseite anzeigen müssen.Dieser Code stellt sicher, dass dies geschieht, da es sich um einen großen Code handelt try/catch um alle Ihre Anfrage-Handler (Servlets, Struts-Aktionen oder einen beliebigen Controller....)

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

}

Stellen Sie sich als weiteres Beispiel vor, Sie haben eine Serviceklasse, die dem Geldtransfergeschäft dient.Diese Methode gibt eine TransferReceipt wenn die Übertragung erfolgt ist oder NULL wenn es nicht könnte.

String FoundtransferService.doTransfer( fundtransferVO);

Jetzt stellen Sie sich vor, Sie erhalten eine List von Geldtransfers vom Benutzer und Sie müssen den oben genannten Service nutzen, um sie alle zu erledigen.

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

Aber was passiert, wenn jeder ausnahme passiert?Sie sollten nicht aufhören, da eine Übertragung möglicherweise erfolgreich war und eine möglicherweise nicht, sollten Sie alle Benutzer weiter durchlaufen List, und zeigen Sie das Ergebnis bei jeder Übertragung an.Sie enden also mit diesem Code.

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

Sie können viele Open-Source-Projekte durchsuchen, um zu sehen, dass die throwable wird wirklich zwischengespeichert und gehandhabt.Hier ist zum Beispiel eine Suche nach tomcat,struts2 und 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

Die Frage ist etwas vage;fragst du "Ist es in Ordnung zu fangen Throwable", oder "ist es in Ordnung, einen zu fangen Throwable und nichts tun"?Viele Leute hier haben letzteres beantwortet, aber das ist ein Nebenproblem;In 99% der Fälle sollten Sie die Ausnahme nicht "konsumieren" oder verwerfen, unabhängig davon, ob Sie fangen Throwable oder IOException oder was auch immer.

Wenn Sie die Ausnahme verbreiten, lautet die Antwort (wie die Antwort auf so viele Fragen) "es kommt darauf an".Es hängt davon ab, was Sie mit der Ausnahme tun — warum Sie es fangen.

Ein gutes Beispiel dafür, warum Sie fangen möchten Throwable ist es, eine Art Bereinigung bereitzustellen, wenn ein Fehler auftritt.Wenn beispielsweise in JDBC während einer Transaktion ein Fehler auftritt, möchten Sie die Transaktion zurücksetzen:

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

Beachten Sie, dass die Ausnahme nicht verworfen, sondern weitergegeben wird.

Aber als allgemeine Politik, fangen Throwable weil Sie keinen Grund haben und zu faul sind zu sehen, welche spezifischen Ausnahmen geworfen werden, ist schlechte Form und eine schlechte Idee.

Im Allgemeinen möchten Sie vermeiden, zu fangen Errors aber ich kann mir (mindestens) zwei spezielle Fälle vorstellen, in denen es angebracht ist, dies zu tun:

  • Sie möchten die Anwendung als Reaktion auf Fehler herunterfahren, insbesondere AssertionError was sonst harmlos ist.
  • Implementieren Sie einen ähnlichen Thread-Pooling-Mechanismus wie Testamentsvollstreckerservice.abgeben() dazu müssen Sie Ausnahmen an den Benutzer zurückleiten, damit dieser damit umgehen kann.

Wenn wir throwable verwenden, dann deckt es fehler auch ab und das ist es.

Beispiel.

generasacodicetagpre.

}

Ausgabe:

generasacodicetagpre.

Wurfbar ist die Superklasse aller Fehler und -beleuchtungen. Wenn Sie in einer Catch-Klausel mit einem Wurf-Klausel einsetzen, fängt es nicht nur alle Ausnahmen, sondern fängt auch alle Fehler auf.Fehler werden von der JVM geworfen, um ernsthafte Probleme anzuzeigen, die nicht von einer Anwendung behandelt werden sollen.Typische Beispiele dafür sind der OutofMemeMemoryError oder der Stackoverflowerror.Beide werden durch Situationen verursacht, die außerhalb der Kontrolle der Anwendung liegen und nicht behandelt werden können.Sie sollten also nicht Wurfablässe fangen, es sei denn, Sie sind ziemlich zuversichtlich, dass es nur eine Ausnahme ist, die sich in einem Wurfweg befindet.

Während es im Allgemeinen eine schlechte Praxis ist, wurfbare Gegenstände zu fangen (wie die zahlreichen Antworten auf diese Frage zeigen), sind die Szenarien, in denen gefangen wird Throwable ist nützlich sind durchaus üblich.Lassen Sie mich einen solchen Fall, den ich bei meiner Arbeit verwende, anhand eines vereinfachten Beispiels erläutern.

Stellen Sie sich eine Methode vor, die das Hinzufügen von zwei Zahlen durchführt und nach erfolgreichem Hinzufügen eine E-Mail-Benachrichtigung an bestimmte Personen sendet.Angenommen, die zurückgegebene Nummer ist wichtig und wird von der aufrufenden Methode verwendet.

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
    }
}

Der Code zum Senden von E-Mail-Benachrichtigungen liest viele Systemkonfigurationen und daher kann es eine Vielzahl von Ausnahmen geben, die von diesem Codeblock ausgelöst werden.Wir möchten jedoch nicht, dass eine Ausnahme, die während des Warnungsversands auftritt, an die Aufrufermethode weitergegeben wird, da sich diese Methode lediglich mit der Summe der beiden von ihr bereitgestellten ganzzahligen Werte befasst.Daher wird der Code zum Versenden von E-Mail-Benachrichtigungen in einem try-catch block, wo Throwable wird abgefangen und alle Ausnahmen werden lediglich protokolliert, sodass der Rest des Flusses fortgesetzt werden kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top