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 spezifisch wie möglich sein?
java
exception-handling
throwable
ktulinho
quelle
quelle
Antworten:
Sie müssen so genau wie möglich sein. Andernfalls könnten unvorhergesehene Fehler auf diese Weise verschwinden.
Außerdem auch
Throwable
AbdeckungenError
und das ist normalerweise kein Punkt der Rückkehr . Sie möchten das nicht fangen / handhaben, Sie möchten, dass Ihr Programm sofort stirbt, damit Sie es richtig reparieren können.quelle
Das ist eine schlechte Idee. In der Tat ist sogar das Fangen
Exception
normalerweise eine schlechte Idee. Betrachten wir ein Beispiel:Nehmen wir nun an, getUserInput () blockiert für eine Weile und ein anderer Thread stoppt Ihren Thread auf die schlechteste Art und Weise (es ruft thread.stop () auf). Ihr catch-Block wird einen
ThreadDeath
Fehler abfangen . Das ist super schlecht. Das Verhalten Ihres Codes nach dem Abfangen dieser Ausnahme ist weitgehend undefiniert.Ein ähnliches Problem tritt beim Abfangen von Exception auf. Möglicherweise
getUserInput()
fehlgeschlagen aufgrund einer InterruptException oder einer Ausnahme, bei der die Berechtigung verweigert wurde, während versucht wurde, die Ergebnisse zu protokollieren, oder aufgrund aller möglichen anderen 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 Ausnahmen ab, mit denen Sie umgehen können:
2 - Wirf alle Ausnahmen zurück, auf die du stößt und die nicht zu handhaben sind:
3 - Verwenden Sie einen finally-Block, damit Sie nicht daran denken müssen, erneut zu werfen:
quelle
throw new Exception("Some additional info, eg. userId " + userId, e);
. Dies wird in einer schönen Ausnahme mit 10 Ursachen protokolliert.Beachten
Throwable
Sie auch, dass Sie beim Fangen auch fangen können,InterruptedException
was eine besondere Behandlung erfordert. Weitere Informationen finden Sie unter Umgang mit InterruptedException .Wenn Sie nur ungeprüfte Ausnahmen abfangen möchten, können Sie dieses Muster auch berücksichtigen
Auf diese Weise erinnert Sie der Compiler daran, wenn Sie Ihren Code ändern und einen Methodenaufruf hinzufügen, der eine aktivierte Ausnahme auslösen kann, und Sie können dann entscheiden, was für diesen Fall zu tun ist.
quelle
direkt aus dem Javadoc der Error-Klasse (die empfiehlt, diese nicht zu fangen):
quelle
Es ist keine schlechte Praxis, wenn Sie absolut keine Ausnahmeblase aus einer Methode haben können.
Es ist eine schlechte Praxis, wenn Sie die Ausnahme wirklich nicht behandeln können. Es ist besser, der Methodensignatur "Würfe" hinzuzufügen, als sie nur zu fangen und erneut zu werfen oder, schlimmer noch, sie in eine RuntimeException zu verpacken und erneut zu werfen.
quelle
Throwable
Instanzen - z. B. für die benutzerdefinierte Ausnahmeprotokollierung.Catching Throwable ist manchmal erforderlich, wenn Sie Bibliotheken verwenden, die Fehler mit Begeisterung auslösen. Andernfalls kann Ihre Bibliothek Ihre Anwendung beenden.
Unter diesen Umständen ist es jedoch am besten, nur die spezifischen Fehler anzugeben, die von der Bibliothek ausgelöst werden, und nicht alle Throwables.
quelle
Throwable ist die Basisklasse für alle Klassen, die ausgelöst werden können (nicht nur Ausnahmen). Sie können wenig tun, wenn Sie einen OutOfMemoryError oder KernelError abfangen (siehe Wann java.lang.Error abfangen? )
Ausnahmen zu fangen sollte ausreichen.
quelle
Dies hängt von Ihrer Logik ab oder davon, ob Sie Ihre Optionen / Möglichkeiten genauer kennen. Wenn es eine bestimmte Ausnahme gibt, auf die Sie möglicherweise sinnvoll reagieren können, können Sie sie zuerst abfangen und dies tun.
Wenn dies nicht der Fall ist und Sie sicher sind, dass Sie für alle Ausnahmen und Fehler dasselbe tun werden (z. B. mit einer Fehlermeldung beenden), ist es kein Problem, den Wurf zu fangen.
Normalerweise gilt der erste Fall und Sie würden den Wurf nicht fangen. Aber es gibt immer noch viele Fälle, in denen das Fangen gut funktioniert.
quelle
Obwohl es als sehr schlechte Praxis beschrieben wird, können Sie manchmal seltene Fälle finden, in denen es nicht nur nützlich, sondern auch obligatorisch ist. Hier sind zwei Beispiele.
In einer Webanwendung, in der Sie dem Benutzer eine vollständige Fehlerseite anzeigen müssen. Dieser Code stellt sicher, dass dies geschieht, da er sich
try/catch
um alle Ihre Anforderungshandler (Servlets, Struts-Aktionen oder Controller) dreht.}}
Stellen Sie sich als weiteres Beispiel eine Serviceklasse vor, die dem Geldtransfergeschäft dient. Diese Methode gibt a zurück,
TransferReceipt
wenn die Übertragung abgeschlossen ist oderNULL
nicht.Im Imaging erhalten Sie eine
List
Überweisung vom Benutzer, und Sie müssen den oben genannten Service verwenden, um alle Transaktionen durchzuführen.Aber was passiert, wenn eine Ausnahme auftritt? Sie sollten nicht aufhören, da eine Übertragung möglicherweise erfolgreich war und eine nicht. Sie sollten alle Benutzer weiter verfolgen
List
und das Ergebnis jeder Übertragung anzeigen. Sie erhalten also diesen Code.Sie können viele Open Source-Projekte durchsuchen, um festzustellen, ob das
throwable
wirklich zwischengespeichert und verarbeitet ist. Zum Beispiel ist hier eine Suche nachtomcat
,struts2
undprimefaces
: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
quelle
throwable
, worum es in dieser Frage gehtDie Frage ist etwas vage; Fragen Sie "Ist es in Ordnung zu fangen
Throwable
" oder "Ist es in Ordnung, einen zu fangenThrowable
und nichts zu tun"? Viele Leute hier antworteten auf Letzteres, aber das ist ein Nebenproblem; 99% der Zeit , die Sie sollten nicht „verbrauchen“ oder die Ausnahme verwerfen, ob Sie fangenThrowable
oderIOException
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 abfangen möchten,
Throwable
ist die Bereitstellung einer Bereinigung, wenn ein Fehler auftritt. Wenn beispielsweise in JDBC während einer Transaktion ein Fehler auftritt, möchten Sie die Transaktion zurücksetzen:Beachten Sie, dass die Ausnahme nicht verworfen, sondern weitergegeben wird.
Aber als allgemeine Richtlinie ist das Fangen,
Throwable
weil Sie keinen Grund haben und zu faul sind, um zu sehen, welche spezifischen Ausnahmen ausgelöst werden, eine schlechte Form und eine schlechte Idee.quelle
Im Allgemeinen möchten Sie vermeiden,
Error
s zu fangen, aber ich kann mir (mindestens) zwei spezielle Fälle vorstellen, in denen dies angebracht ist:AssertionError
diese ansonsten harmlos sind.quelle
Wenn wir Throwable verwenden , deckt es auch Error ab und das wars.
Beispiel.
}}
Ausgabe:
quelle
Wurfbar ist die Oberklasse aller Fehler und Erschöpfungen. Wenn Sie Throwable in einer catch-Klausel verwenden, werden nicht nur alle Ausnahmen, sondern auch alle Fehler abgefangen. Die JVM gibt Fehler aus, um auf schwerwiegende Probleme hinzuweisen, die nicht von einer Anwendung behandelt werden sollen. Typische Beispiele hierfür sind der OutOfMemoryError oder der StackOverflowError. Beides wird durch Situationen verursacht, die außerhalb der Kontrolle der Anwendung liegen und nicht behandelt werden können. Sie sollten Throwables also nicht fangen, es sei denn, Sie sind ziemlich sicher, dass es sich nur um eine Ausnahme in Throwable handelt.
quelle
Während es im Allgemeinen eine schlechte Praxis ist, Throwable zu fangen (wie aus den zahlreichen Antworten auf diese Frage hervorgeht), sind die Szenarien, in denen das Fangen
Throwable
nützlich ist, weit verbreitet. Lassen Sie mich einen solchen Fall, den ich bei meiner Arbeit verwende, anhand eines vereinfachten Beispiels erläutern.Stellen Sie sich eine Methode vor, bei der zwei Zahlen hinzugefügt werden und nach erfolgreicher Hinzufügung eine E-Mail-Benachrichtigung an bestimmte Personen gesendet wird. Angenommen, die zurückgegebene Nummer ist wichtig und wird von der aufrufenden Methode verwendet.
Der Code zum Senden von E-Mail-Warnungen 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 Alarmversands auftritt, an die Aufrufermethode weitergegeben wird, da diese Methode lediglich die Summe der beiden bereitgestellten Ganzzahlwerte betrifft. Daher wird der Code zum Versenden von E-Mail-Benachrichtigungen in einem
try-catch
Block abgelegt, in demThrowable
alle Ausnahmen abgefangen und protokolliert werden, sodass der Rest des Flusses fortgesetzt werden kann.quelle
Exception
auf jeden Fall, aber nichtThrowable
.