Ist es sinnvoll, "endlich versuchen" ohne "fangen" zu machen?


127

Ich habe einen Code wie diesen gesehen:

    try
    {
        db.store(mydata);
    }
    finally
    {
        db.cleanup();
    }

Ich dachte trysoll ein haben catch?

Warum macht dieser Code das so?


1
Es stellt sicher, dass die Bereinigung wie in anderen Antworten erwähnt erfolgt, insbesondere für fopen
Dateihandles

Antworten:


181

Dies ist nützlich, wenn die aktuell ausgeführte Methode die Ausnahme weiterhin auslösen soll, während Ressourcen ordnungsgemäß bereinigt werden können. Im Folgenden finden Sie ein konkretes Beispiel für die Behandlung der Ausnahme von einer aufrufenden Methode.

public void yourOtherMethod() {
    try {
        yourMethod();
    } catch (YourException ex) {
        // handle exception
    }
}    

public void yourMethod() throws YourException {
    try {
        db.store(mydata);
    } finally {
        db.cleanup();
    }
}

17
häufig verwendet mit Sperren wie in: lock.lock (); versuchen Sie {/ * gesperrt * /} endlich {lock.unlock ()}
Minuten

Was passiert, wenn eine Ausnahme endgültig ausgelöst wird?
Barth

1
@barth Wenn kein catchBlock vorhanden ist, wird die eingeworfene Ausnahme finallyvor einer Ausnahme im tryBlock ausgeführt. Wenn es also zwei Ausnahmen gibt, eine in tryund eine in finallyder einzigen Ausnahme, die ausgelöst wird, ist die in finally. Dieses Verhalten ist in PHP und Python nicht dasselbe, da beide Ausnahmen in diesen Sprachen gleichzeitig ausgelöst werden und die Reihenfolge der Ausnahmen tryzuerst und dann ist finally.
Regen

72

Es ist da, weil der Programmierer sicherstellen wollte, dass db.cleanup()es aufgerufen wird, auch wenn der Code im try-Block eine Ausnahme auslöst. Ausnahmen werden von diesem Block nicht behandelt, aber erst nach Ausführung des finally-Blocks nach oben weitergegeben.


23
+1 Genau. Das tryist nur da, um das zu ermöglichen finally. Ausnahmen werden nicht erfasst.
Zockman

2
+1, um zu verdeutlichen, dass die Ausnahme den Stapel fortsetzt, bis sie abgefangen wird. Danke
Code Jockey

20

Warum macht dieser Code das so?

Denn anscheinend weiß der Code nicht, wie er mit Ausnahmen auf dieser Ebene umgehen soll. Das ist gut - solange einer der Anrufer dies tut, dh solange die Ausnahme letztendlich irgendwo behandelt wird.

Low-Level-Code kann häufig nicht angemessen auf Ausnahmen reagieren, da der Benutzer benachrichtigt oder die Ausnahme protokolliert oder eine andere Strategie ausprobiert werden muss. Low-Level-Code führt eine aus Funktion aus und weiß nichts über Entscheidungen auf höherer Ebene.

Der Code muss jedoch noch seine Ressourcen bereinigen (denn wenn dies nicht der Fall ist, würden sie auslaufen). Dies geschieht genau in der finallyKlausel, um sicherzustellen, dass es immer passiert, ob eine Ausnahme ausgelöst wurde oder nicht.


2

Der finally-Block stellt sicher, dass auch dann, wenn eine RuntimeException ausgelöst wird (möglicherweise aufgrund eines Fehlers im aufgerufenen Code), die db.cleanup() Aufruf .

Dies wird auch häufig verwendet, um zu viel Verschachtelung zu verhindern:

try
{
    if (foo) return false;
    //bla ...
    return true;
}
finally
{
    //clean up
}

Insbesondere wenn es viele Punkte gibt, an denen die Methode zurückgegeben wird, verbessert dies die Lesbarkeit, da jeder sehen kann, dass der Bereinigungscode in jedem Fall aufgerufen wird.


0

Der Code tut dies, um sicherzustellen, dass die Datenbank geschlossen ist.
Normalerweise müssen Sie den gesamten Code für den Datenbankzugriff in den try-Block einfügen und dann einen Aufruf zum Schließen der Datenbank im finally-Block ausführen.
Die Art und Weise, wie try ... finally funktioniert, bedeutet, dass der Code im try-Block ausgeführt wird und der Code im finally-Block ausgeführt wird, wenn dies abgeschlossen ist ... egal was passiert.
Kurz bevor der Computer von der Wand gerissen wird, wird der Computer schließlich ausgeführt.
Dies bedeutet, dass selbst wenn eine Ausnahme aufgerufen wird und die Ausführung der Methode drei Jahre dauert, diese weiterhin im finally-Block gespeichert wird und die Datenbank geschlossen wird.


0

Wenn einer der Codes im try-Block eine aktivierte Ausnahme auslösen kann, muss er in der throw-Klausel der Methodensignatur erscheinen. Wenn eine nicht aktivierte Ausnahme ausgelöst wird, wird sie aus der Methode entfernt.

Der finally-Block wird immer ausgeführt, unabhängig davon, ob eine Ausnahme ausgelöst wird oder nicht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.