Gibt es eine elegante Möglichkeit, Ausnahmen zu behandeln, die in finally
Block geworfen werden ?
Beispielsweise:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
Wie vermeidest du das try
/ catch
im finally
Block?
Resource
=>Closeable
?Normalerweise verwende ich eine der folgenden
closeQuietly
Methodenorg.apache.commons.io.IOUtils
:quelle
Wenn Sie Java 7 verwenden und
resource
implementierenAutoClosable
, können Sie dies tun (am Beispiel von InputStream):quelle
Wahrscheinlich etwas übertrieben, aber vielleicht nützlich, wenn Sie Ausnahmen in die Luft sprudeln lassen und nichts aus Ihrer Methode heraus protokollieren können (z. B. weil es sich um eine Bibliothek handelt und Sie den aufrufenden Code lieber Ausnahmen und Protokollierung behandeln lassen möchten):
UPDATE: Ich habe mir das etwas genauer angesehen und einen großartigen Blog-Beitrag von jemandem gefunden, der klar mehr darüber nachgedacht hat als ich: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Er geht noch einen Schritt weiter und kombiniert die beiden Ausnahmen zu einer, was ich in einigen Fällen als nützlich erachten könnte.
quelle
ignore
Ausnahme protokollierenAb Java 7 müssen Sie die Ressourcen in einem finally- Block nicht mehr explizit schließen , sondern können try verwenden Syntax with-resources verwenden. Die try-with-resources-Anweisung ist eine try-Anweisung, die eine oder mehrere Ressourcen deklariert. Eine Ressource ist ein Objekt, das geschlossen werden muss, nachdem das Programm damit beendet wurde. Die Anweisung try-with-resources stellt sicher, dass jede Ressource am Ende der Anweisung geschlossen wird. Jedes Objekt, das java.lang.AutoCloseable implementiert, einschließlich aller Objekte, die java.io.Closeable implementieren, kann als Ressource verwendet werden.
Nehmen Sie den folgenden Code an:
Wenn eine Ausnahme auftritt, wird die close- Methode für jede dieser drei Ressourcen in umgekehrter Reihenfolge aufgerufen, in der sie erstellt wurden. Dies bedeutet, dass die Methode close zuerst für ResultSetm, dann für die Anweisung und am Ende für das Connection-Objekt aufgerufen wird.
Es ist auch wichtig zu wissen, dass alle Ausnahmen, die auftreten, wenn die close-Methoden automatisch aufgerufen werden, unterdrückt werden. Diese unterdrückten Ausnahmen können mit der in der Throwable- Klasse definierten Methode getsuppressed () abgerufen werden .
Quelle: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
quelle
Das Ignorieren von Ausnahmen, die in einem 'finally'-Block auftreten, ist im Allgemeinen eine schlechte Idee, es sei denn, man weiß, wie diese Ausnahmen aussehen und welche Bedingungen sie darstellen. Im normalen
try/finally
Verwendungsmuster versetzt dertry
Block die Dinge in einen Zustand, den der externe Code nicht erwartet, und denfinally
Block stellt den Zustand dieser Dinge auf den vom externen Code erwarteten Zustand wieder her. Externer Code, der eine Ausnahme abfängt, erwartet im Allgemeinen, dass trotz der Ausnahme alles in a wiederhergestellt wurdenormal
Zustand. Angenommen, ein Code startet eine Transaktion und versucht dann, zwei Datensätze hinzuzufügen. Der Block "finally" führt eine Operation "Rollback, wenn nicht festgeschrieben" aus. Ein Aufrufer kann darauf vorbereitet sein, dass während der Ausführung der zweiten "Hinzufügen" -Operation eine Ausnahme auftritt, und kann erwarten, dass sich die Datenbank in dem Zustand befindet, in dem sie sich befand, bevor eine der beiden Operationen versucht wurde, wenn eine solche Ausnahme abgefangen wird. Wenn jedoch während des Rollbacks eine zweite Ausnahme auftritt, können schlimme Dinge passieren, wenn der Aufrufer Annahmen über den Datenbankstatus trifft. Der Rollback-Fehler stellt eine große Krise dar - eine, die nicht vom Code erfasst werden sollte, der lediglich eine Ausnahme "Fehler beim Hinzufügen eines Datensatzes" erwartet.Meine persönliche Neigung wäre es, eine endgültige Methode zu haben, um auftretende Ausnahmen abzufangen und sie in eine "CleanupFailedException" zu packen, um zu erkennen, dass ein solcher Fehler ein großes Problem darstellt und eine solche Ausnahme nicht leichtfertig abgefangen werden sollte.
quelle
Eine Lösung, wenn die beiden Ausnahmen zwei verschiedene Klassen sind
Aber manchmal kann man diesen zweiten Versuch nicht vermeiden. zB zum Schließen eines Streams
quelle
Warum möchten Sie den zusätzlichen Block vermeiden? Da der finally-Block "normale" Operationen enthält, die eine Ausnahme auslösen können UND Sie möchten, dass der finally-Block vollständig ausgeführt wird, MÜSSEN Sie Ausnahmen abfangen.
Wenn Sie nicht erwarten, dass der finally-Block eine Ausnahme auslöst, und Sie ohnehin nicht wissen, wie Sie mit der Ausnahme umgehen sollen (Sie würden nur die Stapelverfolgung ausgeben), lassen Sie die Ausnahme den Aufrufstapel aufblasen (entfernen Sie den try-catch aus dem finally-Block Block).
Wenn Sie die Eingabe reduzieren möchten, können Sie einen "globalen" äußeren Try-Catch-Block implementieren, der alle Ausnahmen abfängt, die in finally-Blöcken ausgelöst werden:
quelle
Nach langem Überlegen finde ich den folgenden Code am besten:
Dieser Code garantiert Folgendes:
quelle
Wenn Sie können, sollten Sie zunächst testen, um den Fehlerzustand zu vermeiden.
Außerdem sollten Sie wahrscheinlich nur Ausnahmen abfangen, von denen Sie sich erholen können. Wenn Sie sich nicht erholen können, lassen Sie es auf die oberste Ebene Ihres Programms übertragen. Wenn Sie nicht auf eine Fehlerbedingung testen können, müssen Sie Ihren Code mit einem Try-Catch-Block umgeben, wie Sie es bereits getan haben (obwohl ich empfehlen würde, immer noch bestimmte, erwartete Fehler abzufangen).
quelle
Sie könnten dies in eine andere Methode umgestalten ...
quelle
Normalerweise mache ich das:
Begründung: Wenn ich mit der Ressource fertig bin und das einzige Problem darin besteht, sie zu schließen, kann ich nicht viel dagegen tun. Es macht auch keinen Sinn, den gesamten Thread zu beenden, wenn ich mit der Ressource sowieso fertig bin.
Dies ist einer der Fälle, in denen es zumindest für mich sicher ist, diese aktivierte Ausnahme zu ignorieren.
Bis heute hatte ich keine Probleme mit dieser Redewendung.
quelle
Job erledigt. Keine Nulltests. Einzelfang, einschließlich Erwerbs- und Freigabeausnahmen. Natürlich können Sie das Execute Around-Idiom verwenden und müssen es für jeden Ressourcentyp nur einmal schreiben.
quelle
Wechsel
Resource
von der besten Antwort zuCloseable
Streams implementiert
Closeable
Somit können Sie die Methode für alle Streams wiederverwendenquelle
Ich bin auf eine ähnliche Situation gestoßen, in der ich try nicht mit Ressourcen verwenden konnte, aber ich wollte auch die Ausnahme behandeln, die vom Schließen herrührt, und nicht nur protokollieren und ignorieren, wie es der closeQuietly-Mechanismus tut. In meinem Fall habe ich es eigentlich nicht mit einem Ausgabestream zu tun, daher ist der Fehler beim Schließen von größerem Interesse als ein einfacher Stream.
quelle