Warum verwenden wir endlich Blöcke?


86

Soweit ich das beurteilen kann, dienen beide folgenden Codefragmente demselben Zweck. Warum überhaupt finallyBlöcke?

Code A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

Code B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

Dies ist nicht spezifisch für C #, es ist eine .Net-Frage
6.

1
Mit java7 nicht mehr erforderlich: AutomaticResourceManagement, try (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Antworten:


136
  • Was passiert, wenn eine Ausnahme ausgelöst wird, die Sie nicht behandeln? (Ich hoffe du fängst nicht Throwable...)
  • Was passiert, wenn Sie aus dem try-Block zurückkehren?
  • Was passiert, wenn der catch-Block eine Ausnahme auslöst?

Ein finallyBlock stellt sicher, dass er ausgeführt wird, unabhängig davon, wie Sie diesen Block verlassen (modulo einige Möglichkeiten, den gesamten Prozess explizit abzubrechen). Das ist wichtig für die deterministische Bereinigung von Ressourcen.


46
Nicht unbedingt wahr; wird schließlich nicht ausgeführt, wenn (1) ein System.exit()Aufruf
vorliegt

2
@Alon try {return 1; } endlich {retrun 2; } Sie erhalten 2
Dennis C

18
@NullUserException: Daher das Bit "Modulo ein paar Wege ..."
Jon Skeet

2
John Skeet lebt hier auf Stackoverflow, jede Frage ist wie ein Klingeln, das er beantworten muss :)
Naikus

1
Dieser Beitrag beschreibt die (seltenen) Bedingungen, unter denen schließlich NICHT aufgerufen werden.
Candamir

12

Beachten Sie, dass (zumindest in Java, wahrscheinlich auch in C #) es auch möglich ist, einen tryBlock ohne a catch, aber mit a zu haben finally. Wenn eine Ausnahme im tryBlock auftritt, wird der Code im finallyBlock ausgeführt, bevor die Ausnahme höher ausgelöst wird:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

7

Möglicherweise möchten Sie den Code einfügen, der ohnehin ausgeführt werden soll, unabhängig davon, was in Ihrem Try- oder Catch-Block passiert.

Auch wenn Sie mehrere catch verwenden und einen Code einfügen möchten, der für alle catch-Blöcke gleich ist, ist dies ein Ort zum Einfügen. Sie können jedoch nicht sicher sein, ob der gesamte versuchte Code ausgeführt wurde.

Beispielsweise:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}

Was ist, wenn ich nicht "endlich" verwende, sondern die Verbindung schließe?
Istiaque Ahmed

5

Schließlich wird immer ausgeführt, wo als Ihr Code nach dem Fang möglicherweise nicht.


warum nicht! Wenn die Ausnahme ordnungsgemäß behandelt wird, wird der Code definitiv ausgeführt.
Mohammad Nadeem

1
@Nadeem: Siehe meine Antwort aus 3 Gründen, es kann nicht passieren.
Jon Skeet

2

Obwohl unsere Anwendung zwangsweise geschlossen wird, müssen einige Aufgaben ausgeführt werden (z. B. Speicherfreigabe, Schließen der Datenbank, Freigabesperre usw.). Wenn Sie diese Codezeilen in den finallyBlock schreiben , wird ausgeführt, ob eine Ausnahme ausgelöst wird oder nicht...

Ihre Anwendung kann eine Sammlung von Threads sein, Exceptionbeendet den Thread, aber nicht die gesamte Anwendung. In diesem Fall finallyist dies nützlicher.

In einigen Fällen finallywerden keine Ausführungen ausgeführt, z. B. JVM-Fehler, Thread-Beendigung usw.


1

Weil Sie diesen Code benötigen, um unabhängig von möglichen Ausnahmen ausgeführt zu werden. Beispielsweise müssen Sie möglicherweise eine nicht verwaltete Ressource bereinigen (das Konstrukt 'using' wird zu einem try / finally-Block kompiliert).


0

Es kann vorkommen, dass Sie einen Code ausführen möchten, egal was passiert. Gibt an, ob eine Ausnahme ausgelöst wird oder nicht. Dann benutzt man finally.


0

finallyWird IMMER ausgeführt, es sei denn, die JVM wurde heruntergefahren, finallybietet nur eine Methode, um den Bereinigungscode an einer Stelle zu platzieren.

Es wäre zu langweilig, wenn Sie den Bereinigungscode in jeden der catchBlöcke einfügen müssten .


0

Wenn der catch-Block eine Ausnahme auslöst, wird der verbleibende Code nicht ausgeführt, daher müssen wir den endgültigen Block schreiben.


0

Schließlich kann Block in Java verwendet werden, um "Bereinigungs" -Code wie das Schließen einer Datei, das Schließen der Verbindung usw. einzufügen.


Der finally-Block wird nicht ausgeführt, wenn das Programm beendet wird (entweder durch Aufrufen von System.exit () oder durch Verursachen eines schwerwiegenden Fehlers, der zum Abbruch des Prozesses führt).


0

Scrollen Sie immer noch nach unten? Bitte schön!

Diese Frage hat mir vor einiger Zeit eine schwere Zeit bereitet.

try
{
 int a=1;
 int b=0;
 int c=a/b;
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}
finally
{
 console.writeline("Finally block");
}
console.writeline("After finally");

Was würde im obigen Szenario gedruckt? Ja hat es richtig erraten:

  • ex.Message - was auch immer es ist (wahrscheinlich versuchte Division durch Null)

  • Schließlich blockieren

  • Nach endlich

    try
    {
        int a=1;
        int b=0;
        int c=a/b;
    }
    catch(Exception ex)
    {
        throw(ex);
    }
    finally
    {
        console.writeline("Finally block");
    }
    console.writeline("After finally");

Was würde dieser Druck? Nichts! Es wird ein Fehler ausgegeben, da der catch-Block einen Fehler ausgelöst hat.

In einer guten Programmierstruktur würden Ihre Ausnahmen in dem Sinne weitergeleitet, dass dieser Code von einer anderen Ebene verarbeitet wird. Um einen solchen Fall zu stimulieren, versuche ich diesen Code.

try
{    
 try
    {
     int a=1;
     int b=0;
     int c=a/b;
    }
    catch(Exception ex)
    {
     throw(ex);
    }
    finally
    {
     console.writeline("Finally block")
    }
    console.writeline("After finally");
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}

In diesem Fall wäre die Ausgabe:

  • Schließlich blockieren
  • ex.Message - was auch immer es ist.

Es ist klar, dass der Code nach dem Auslösen nicht ausgeführt wird, wenn Sie eine Ausnahme abfangen und erneut in andere Ebenen werfen (Trichter). Es verhält sich ähnlich wie eine Rückgabe innerhalb einer Funktion.

Sie wissen jetzt, warum Sie Ihre Ressourcen nicht nach dem catch-Block für Codes schließen müssen. Platzieren Sie sie im finally-Block.

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.