it-swarm-eu.dev

Wird ein finally-Block immer in Java ausgeführt?

Kann ich unter Berücksichtigung dieses Codes absolut sicher sein, dass der Block finally immer ausgeführt wird, unabhängig davon, was something() ist?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}
2226
jonny five

Ja, finally wird nach der Ausführung der Codeblöcke try oder catch aufgerufen.

Die einzigen Zeiten, in denen finally nicht aufgerufen wird, sind:

  1. Wenn Sie System.exit() aufrufen
  2. Wenn die JVM zuerst abstürzt
  3. Wenn die JVM eine Endlosschleife (oder eine andere nicht unterbrechbare, nicht terminierende Anweisung) im Block try oder catch erreicht
  4. Wenn das Betriebssystem den JVM-Prozess zwangsweise beendet; beispielsweise kill -9 <pid> unter UNIX
  5. Wenn das Host-System stirbt; B. Stromausfall, Hardwarefehler, Betriebssystem-Panik usw.
  6. Wenn der Block finally von einem Daemon-Thread ausgeführt wird und alle anderen Nicht-Daemon-Threads beendet werden, bevor finally aufgerufen wird
2491
jodonnell

Beispielcode:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

Ausgabe:

finally trumps return. 
0
520
Kevin

Auch wenn es eine schlechte Praxis ist, wird eine Return-Anweisung innerhalb des finally-Blocks jede andere Return-Anweisung aus dem regulären Block übersteigen. Das heißt, der folgende Block würde false zurückgeben:

try { return true; } finally { return false; }

Gleiches gilt für das Werfen von Ausnahmen aus dem finally-Block.

370
MooBob42

Hier sind die offiziellen Wörter aus der Java Sprachspezifikation.

14.20.2. Ausführung von try-finally und try-catch-finally

Eine try -Anweisung mit einem finally -Block wird ausgeführt, indem zuerst der try -Block ausgeführt wird. Dann gibt es eine Auswahl:

  • Wenn die Ausführung des Blocks try normal abgeschlossen wird, wird [...]
  • Wenn die Ausführung des Blocks try aufgrund eines throw mit einem Wert von V abrupt abgeschlossen wird, [...]
  • Wenn die Ausführung des Blocks try aus einem anderen Grund abrupt abgeschlossen wird R, wird der Block finally ausgeführt. Dann gibt es eine Auswahl:
    • Wenn der finally-Block normal abgeschlossen wird, wird die Anweisung try aus dem Grund R abrupt abgeschlossen.
    • Wenn der Block finally aus folgendem Grund abrupt abgeschlossen wird: S, wird die Anweisung try aus folgendem Grund abrupt abgeschlossen: S ( und Grund R wird verworfen ).

Die Spezifikation für return macht dies tatsächlich explizit:

JLS 14.17 Die return-Anweisung

ReturnStatement:
     return Expression(opt) ;

Eine return -Anweisung ohne Expression versucht , die Steuerung an den Aufrufer der Methode oder des Konstruktors zu übertragen, der sie enthält.

Eine return -Anweisung mit einem Expression versucht , die Steuerung an den Aufrufer der Methode zu übertragen, die sie enthält; Der Wert von Expression wird zum Wert des Methodenaufrufs.

In den vorhergehenden Beschreibungen heißt es " versucht , die Kontrolle zu übertragen" und nicht nur "überträgt die Kontrolle", weil Wenn die Methode oder der Konstruktor try Anweisungen enthält, deren try -Blöcke die return -Anweisung enthalten, werden alle finally -Klauseln dieser try -Anweisungen ausgeführt in der Reihenfolge von innen nach außen, bevor die Steuerung an den Aufrufer der Methode oder des Konstruktors übertragen wird. Das abrupte Abschließen einer finally - Klausel kann die durch eine return - Anweisung ausgelöste Übertragung der Kontrolle unterbrechen.

251

Zusätzlich zu den anderen Antworten muss darauf hingewiesen werden, dass 'finally' das Recht hat, alle Ausnahmen/zurückgegebenen Werte durch den try..catch-Block zu überschreiben. Der folgende Code gibt beispielsweise 12 zurück:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

In ähnlicher Weise löst die folgende Methode keine Ausnahme aus:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

Während die folgende Methode es auslöst:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}
151
Eyal Schneider

Ich habe das obige Beispiel mit leichten Modifikationen ausprobiert.

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

Die obigen Code-Ausgaben:

endlich kehren trümpfe zurück.
2

Dies liegt daran, dass der Block i ausgeführt wird, wenn return i; ausgeführt wird. Danach wird der Block finally ausgeführt, wobei 12 dem Block i und dann System.out out zugewiesen wird ausgeführt wird.

Nach dem Ausführen des Blocks finally gibt der Block try 2 zurück, anstatt 12 zurückzugeben, da diese return-Anweisung nicht erneut ausgeführt wird.

Wenn Sie diesen Code in Eclipse debuggen, haben Sie das Gefühl, dass nach der Ausführung von System.out von finally block die return -Anweisung von try block erneut ausgeführt wird. Dies ist jedoch nicht der Fall. Es wird einfach der Wert 2 zurückgegeben.

111
vibhash

Hier ist eine Ausarbeitung von Kevins Antwort . Es ist wichtig zu wissen, dass der zurückzugebende Ausdruck vor finally ausgewertet wird, auch wenn er nach _ zurückgegeben wird.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

Ausgabe:

X
finally trumps return... sort of
0
101
WoodenKitty

Das ist die ganze Idee eines finalen Blocks. Auf diese Weise können Sie sicherstellen, dass Sie Bereinigungen durchführen, die ansonsten möglicherweise übersprungen werden, da Sie unter anderem natürlich zurückkehren.

Schließlich wird im try-Block nabhängig davon, was passiert aufgerufen (, es sei denn , Sie rufen System.exit(int) oder das Java Virtual Machine tritt aus einem anderen Grund aus.

53
Chris Cooper

Eine logische Art, darüber nachzudenken, ist:

  1. Code, der in einem finally-Block platziert ist, muss ausgeführt werden was auch immer vorkommt innerhalb des try-Blocks
  2. Wenn also der Code im try-Block versucht, einen Wert zurückzugeben oder eine Ausnahme auszulösen, wird der Artikel so lange im Regal abgelegt, bis der finally-Block ausgeführt werden kann
  3. Da Code im finally-Block (per Definition) eine hohe Priorität hat, kann er alles zurückgeben oder werfen, was ihm gefällt. In diesem Fall wird alles, was noch im Regal liegt, verworfen.
  4. Die einzige Ausnahme hiervon besteht darin, dass VM während des Try-Blocks, z. von 'System.exit'
39
Garth Gilmour

finally wird immer ausgeführt, es sei denn, das Programm wird abnormal beendet (z. B. durch Aufrufen von System.exit (0) ..). Ihr Sysout wird also gedruckt

19
shyam

Auch eine Rückkehr in schließlich wird jede Ausnahme wegwerfen. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

19

Der finally-Block wird immer ausgeführt, es sei denn, das Programm wird aufgrund eines JVM-Absturzes oder eines Aufrufs von System.exit(0) abnormal beendet.

Darüber hinaus überschreibt jeder Wert, der aus dem finally-Block zurückgegeben wird, den Wert, der vor der Ausführung des finally-Blocks zurückgegeben wurde. Achten Sie daher darauf, alle Exit-Punkte zu überprüfen, wenn Sie try finally verwenden.

18
user9189

Nein, nicht immer ist ein Ausnahmefall // System.exit (0); vor dem finally-Block wird verhindert, dass finally ausgeführt wird.

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}
18
Rajendra Jadi

Schließlich wird immer ausgeführt, das ist der springende Punkt, nur weil es im Code nach der Rückgabe erscheint, heißt das nicht, dass es so implementiert ist. Die Laufzeitumgebung Java hat die Verantwortung, diesen Code beim Verlassen des Blocks try auszuführen.

Zum Beispiel, wenn Sie Folgendes haben:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

Die Laufzeit generiert ungefähr Folgendes:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

Wenn eine nicht abgefangene Ausnahme ausgelöst wird, wird der Block finally ausgeführt und die Ausnahme wird weiter übertragen.

13
Motti

Dies liegt daran, dass Sie den Wert von i als 12 zugewiesen haben, aber den Wert von i nicht an die Funktion zurückgegeben haben. Der richtige Code lautet wie folgt:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}
11
Wasim

Denn ein finally-Block wird immer aufgerufen, es sei denn, Sie rufen System.exit() auf (oder der Thread stürzt ab).

10
Jay Riggs

Die Antwort ist einfach YES.

INPUT:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

OUTPUT:

catch
finally
10
Meet

Ja, es wird angerufen. Das ist der springende Punkt bei einem finalen Schlüsselwort. Wenn das Herausspringen aus dem try/catch-Block nur den finally-Block überspringen konnte, glich dies dem Platzieren von System.out.println außerhalb des try/catch-Blocks.

9
Mendelt

Ja, schließlich wird der Block immer ausgeführt. Die meisten Entwickler verwenden diesen Block zum Schließen der Datenbankverbindung, des Resultset-Objekts und des Anweisungsobjekts und verwenden ihn auch im Ruhezustand Java, um die Transaktion zurückzusetzen.

9
Gautam Viradiya

In der offiziellen Java -Dokumentation (Klicken Sie auf hier ) steht:

Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. Wenn der Thread, der den Try- oder Catch-Code ausführt, unterbrochen oder beendet wird, wird der finally-Block möglicherweise auch dann nicht ausgeführt, wenn die Anwendung als Ganzes fortgesetzt wird.

9
bikz05

Ja, es wird. Nur falls dies nicht der Fall ist, wird JVM beendet oder stürzt ab

8
abhig

Ja, es wird. Egal, was in Ihrem try- oder catch-Block passiert, sofern nicht anders System.exit () aufgerufen wurde oder die JVM abgestürzt ist. Befindet sich in den Blöcken eine return-Anweisung, wird sie zuletzt vor dieser return-Anweisung ausgeführt.

8
Karthikeyan

Betrachten Sie das folgende Programm:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

Ab Java 1.8.162 gibt der obige Codeblock die folgende Ausgabe aus:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

dies bedeutet, dass die Verwendung von finally zum Freigeben von Objekten eine bewährte Methode ist, die dem folgenden Code entspricht:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}
8
Samim

Hinzufügen zu @ vibhashs Antwort , da keine andere Antwort erklärt, was bei einem veränderlichen Objekt wie dem folgenden passiert.

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

Wird ausgegeben

sbupdated 
8

finally wird ausgeführt und das ist sicher.

finally wird in den folgenden Fällen nicht ausgeführt:

fall 1 :

Wenn Sie System.exit() ausführen.

fall 2:

Wenn Ihre JVM/Thread abstürzt.

fall 3:

Wenn Ihre Ausführung zwischen manuell gestoppt wird.

7
Utkash Bhatt

Das Gleiche gilt für eine Ausnahme, abgesehen von dem Punkt, dass eine Rückgabe im try-Block endgültig ersetzt werden muss. Ein finally-Block, der eine Ausnahme auslöst, ersetzt eine Rückgabe oder Ausnahme, die aus dem try-Block ausgelöst wird.

7
Alex Miller

Das ist in jeder Sprache der Fall ... wird letztendlich immer vor einer return-Anweisung ausgeführt, unabhängig davon, wo sich diese return-Anweisung im Methodentext befindet. Wenn das nicht der Fall wäre, hätte der finally-Block keine große Bedeutung.

7
Scott Dorman

Ich habe es versucht, es ist Single-Threaded.

class Test {
    public static void main(String args[]) throws Exception {
       Object obj = new Object();
       try {
            synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
           }
       } catch (Exception e) {
       } finally {
           System.out.println("finally");
       }
   }
}

Der Haupt-Thread wird für immer im Wartezustand sein, daher wird er letztendlich niemals aufgerufen.

die Konsolenausgabe druckt keine Zeichenfolge: after wait() oder finally

In Übereinstimmung mit @Stephen C ist das obige Beispiel eine der Erwähnungen des 3. Falls hier :

Hinzufügen weiterer solcher Endlosschleifenmöglichkeiten in folgendem Code:

// import Java.util.concurrent.Semaphore;
class Test {
    public static void main(String[] args) {
        try {
            // Thread.sleep(Long.MAX_VALUE);
            // Thread.currentThread().join();
            // new Semaphore(0).acquire();
            // while (true){}
            System.out.println("after sleep join semaphore exit infinite while loop");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }
}

Fall 2: Wenn die JVM zuerst abstürzt

import Sun.misc.Unsafe;
import Java.lang.reflect.Field;
class Test {
    public static void main(String args[]) {
        try {
            unsafeMethod();
//            Runtime.getRuntime().halt(123);
            System.out.println("After Jvm Crash!");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }

    private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        unsafe.putAddress(0, 0);
    }
}

Ref: Wie stürzt eine JVM ab?

Fall 6: Wenn finally vom Daemon-Thread ausgeführt wird und alle anderen Nicht-Daemon-Threads vor finally beendet werden, wird finally aufgerufen.

class Test {
    public static void main(String args[]) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    printThreads("Daemon Thread printing");
                    // just to ensure this thread will live longer than main thread
                    Thread.sleep(10000);
                } catch (Exception e) {
                } finally {
                    System.out.println("finally");
                }
            }
        };
        Thread daemonThread = new Thread(runnable);
        daemonThread.setDaemon(Boolean.TRUE);
        daemonThread.setName("My Daemon Thread");
        daemonThread.start();
        printThreads("main Thread Printing");
    }

    private static synchronized void printThreads(String str) {
        System.out.println(str);
        int threadCount = 0;
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for (Thread t : threadSet) {
            if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                ++threadCount;
            }
        }
        System.out.println("Thread count started by Main thread:" + threadCount);
        System.out.println("-------------------------------------------------");
    }
}

ausgabe: Dies gibt nicht "finally" aus, was bedeutet, dass "finally block" in "daemon thread" nicht ausgeführt wurde

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0
6
dkb

Ja, da keine Steueranweisung die Ausführung von finally verhindern kann.

Hier ist ein Referenzbeispiel, in dem alle Codeblöcke ausgeführt werden:

| x | Current result | Code 
|---|----------------|------ - - -
|   |                |     
|   |                | public static int finallyTest() {
| 3 |                |     int x = 3;
|   |                |     try {
|   |                |        try {
| 4 |                |             x++;
| 4 | return 4       |             return x;
|   |                |         } finally {
| 3 |                |             x--;
| 3 | throw          |             throw new RuntimeException("Ahh!");
|   |                |         }
|   |                |     } catch (RuntimeException e) {
| 4 | return 4       |         return ++x;
|   |                |     } finally {
| 3 |                |         x--;
|   |                |     }
|   |                | }
|   |                |
|---|----------------|------ - - -
|   | Result: 4      |

In der folgenden Variante wird return x; übersprungen. Ergebnis ist noch 4:

public static int finallyTest() {
    int x = 3;
    try {
        try {
            x++;
            if (true) throw new RuntimeException("Ahh!");
            return x; // skipped
        } finally {
            x--;
        }
    } catch (RuntimeException e) {
        return ++x;
    } finally {
        x--;
    }
}

Referenzen verfolgen natürlich ihren Status. Dieses Beispiel gibt eine Referenz mit value = 4 zurück:

static class IntRef { public int value; }
public static IntRef finallyTest() {
    IntRef x = new IntRef();
    x.value = 3;
    try {
        return x;
    } finally {
        x.value++; // will be tracked even after return
    }
}
6
Dávid Horváth

Wenn Sie keine Ausnahmebedingung behandeln, führt JVM vor dem Beenden des Programms den Block finally aus. Es wird nur dann nicht ausgeführt, wenn die normale Ausführung des Programms aufgrund der folgenden Gründe fehlschlägt.

  1. Indem ein schwerwiegender Fehler verursacht wird, durch den der Prozess abgebrochen wird.

  2. Programmabbruch aufgrund fehlerhaften Speichers.

  3. Durch Aufrufen von System.exit ()

  4. Wenn das Programm in die Endlosschleife geht.

6

NICHT IMMER

Die Java -Sprachenspezifikation beschreibt, wie die try-catch-finally- und try-catch-Blöcke bei 14.20.2 funktionieren
An keiner Stelle wird angegeben, dass der finally-Block immer ausgeführt wird. Für alle Fälle, in denen der try-catch-finally- und der try-finally-Block abgeschlossen sind, wird jedoch festgelegt, dass die Ausführung vor Abschluss abgeschlossen sein muss.

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

Das JLS garantiert nicht, dass FIN ausgeführt wird, nachdem CODE. Das JLS garantiert, dass wenn CODE und NEXT ausgeführt werden dann wird FIN immer nach CODE und vorher ausgeführt NEXT.

Warum garantiert die JLS nicht, dass der finally-Block immer nach dem try-Block ausgeführt wird? Weil es unmöglich ist. Es ist unwahrscheinlich, aber möglich, dass die JVM unmittelbar nach Abschluss des try-Blocks, jedoch vor der Ausführung des finally-Blocks, abgebrochen wird (kill, crash, power off). Das JLS kann nichts dagegen unternehmen.

Jede Software, die für ihr korrektes Verhalten davon abhängt, dass Blöcke ausgeführt werden, nachdem ihre Try-Blöcke abgeschlossen sind, ist fehlerhaft.

Rückgaben im try-Block sind für dieses Problem irrelevant. Wenn die Ausführung den Code nach dem try-catch-finally erreicht, ist garantiert, dass der finally-Block zuvor ausgeführt wurde, mit oder ohne Rückgabe innerhalb des try-Blocks.

  1. Schließlich wird Block immer ausgeführt. Es sei denn und bis System.exit () Anweisung vorhanden ist (erste Anweisung im finally-Block).
  2. Wenn system.exit () die erste Anweisung ist, wird der finally-Block nicht ausgeführt und die Steuerung kommt aus dem finally-Block. Immer wenn die Anweisung System.exit () in finally-Block gelangt, bis der Anweisungsblock finally ausgeführt wird, und wenn System.exit () angezeigt wird, wird die Steuerkraft vollständig aus dem finally-Block ausgegeben.
6
Avinash Pande

try- catch- finally sind die Schlüsselwörter für die Verwendung des Ausnahmebehandlungsfalls.
Wie üblich erklärend

try {
     //code statements
     //exception thrown here
     //lines not reached if exception thrown
} catch (Exception e) {
    //lines reached only when exception is thrown
} finally {
    // always executed when the try block is exited
    //independent of an exception thrown or not
}

Der finally-Block verhindert die Ausführung ...

  • Wenn Sie System.exit(0); aufgerufen haben
  • Wenn JVM beendet wird.
  • Fehler in der JVM

Der finally-Block wird in einigen eindeutigen Szenarien nicht nach der Rückkehr aufgerufen: Wenn zuerst System.exit () aufgerufen wird oder wenn die JVM abstürzt.

Lassen Sie mich versuchen, Ihre Frage so einfach wie möglich zu beantworten.

Regel 1 : Der finally-Block wird immer ausgeführt (obwohl es Ausnahmen gibt. Aber bleiben wir für einige Zeit dabei.)

Regel 2 : Die Anweisungen im finally-Block werden ausgeführt, wenn die Steuerung einen try- oder catch-Block verlässt. Die Übertragung der Steuerung kann als Ergebnis einer normalen Ausführung erfolgen von der Ausführung einer break, continue, goto oder return-Anweisung oder einer Propogation einer Exception.

Im Falle einer bestimmten return-Anweisung (seit ihrer Überschrift) muss die Steuerung die aufrufende Methode verlassen und ruft daher den finally-Block der entsprechenden try-finally-Struktur auf. Die return-Anweisung wird nach dem finally-Block ausgeführt.

Falls es auch im finally-Block eine return-Anweisung gibt, wird diese definitiv diejenige überschreiben, die am try-Block ansteht, da sie den Aufrufstapel löscht.

Eine bessere Erklärung finden Sie hier: http://msdn.Microsoft.com/en-us/ .... Das Konzept ist in allen Hochsprachen weitgehend identisch.

5
Sandip Solanki

Ja, es steht geschrieben hier

Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. Wenn der Thread, der den Try- oder Catch-Code ausführt, unterbrochen oder beendet wird, wird der finally-Block möglicherweise auch dann nicht ausgeführt, wenn die Anwendung als Ganzes fortgesetzt wird.

4

Der Block finally wird immer ausgeführt, unabhängig davon, ob die Ausnahmebehandlung ausgeführt wurde oder nicht. Wenn vor dem Block try eine Ausnahme aufgetreten ist, wird der Block finally nicht ausgeführt.

4
Rohit Chugh

Wenn eine Ausnahme ausgelöst wird, läuft schließlich. Wenn eine Ausnahme nicht ausgelöst wird, wird sie schließlich ausgeführt. Wenn die Ausnahme abgefangen wird, läuft schließlich. Wenn die Ausnahme nicht abgefangen wird, läuft schließlich.

Es wird nur dann nicht ausgeführt, wenn JVM beendet wird.

4
Bhushan

Probieren Sie diesen Code aus, Sie werden verstehen, dass Code im finally-Block wird nach der return-Anweisung ausgeführt.

public class TestTryCatchFinally {
    static int x = 0;

    public static void main(String[] args){
        System.out.println(f1() );
        System.out.println(f2() );
    }

    public static int f1(){
        try{
            x = 1;
            return x;
        }finally{
            x = 2;
        }
    }

    public static int f2(){
        return x;
    }
}
4
eric2323223

Ich war sehr verwirrt mit all den Antworten in verschiedenen Foren und entschied mich, endlich zu codieren und zu sehen. Die Ausgabe ist:

wird schließlich ausgeführt, auch wenn im try and catch-Block return angegeben ist.

try {  
  System.out.println("try"); 
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} catch (Exception e) {   
  System.out.println("catch");
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} finally {  
   System.out.println("Print me FINALLY");
}

Ausgabe

versuchen

Drucken Sie mich endlich

  1. Wenn in try and catch block im obigen Code return durch System.exit(0) ersetzt wird und aus irgendeinem Grund eine Ausnahme davor auftritt.
4
milton

Gleich mit folgendem Code:

static int f() {
    while (true) {
        try {
            return 1;
        } finally {
            break;
        }
    }
    return 2;
}

f wird 2 zurückgeben!

3
dibo

Denn das Finale wird immer aufgerufen, in welchen Fällen auch immer Sie haben. Sie haben keine Ausnahme, es heißt immer noch, catch exception, es heißt immer noch

3
vodkhang

finally kann auch vorzeitig beendet werden, wenn eine Ausnahme in einem verschachtelten finally-Block ausgelöst wird. Der Compiler warnt Sie, dass der finally-Block nicht normal ausgeführt wird, oder gibt einen Fehler aus, dass Sie nicht erreichbaren Code haben. Der Fehler für nicht erreichbaren Code wird nur angezeigt, wenn sich der Wurf nicht hinter einer bedingten Anweisung oder innerhalb einer Schleife befindet.

try{
}finally{
   try{
   }finally{
      //if(someCondition) --> no error because of unreachable code
      throw new RunTimeException();
   }
   int a = 5;//unreachable code
}
3

Ja, es wird immer aufgerufen, aber in einer Situation wird es nicht aufgerufen, wenn Sie System.exit () verwenden.

try{
//risky code
}catch(Exception e){
//exception handling code
}
finally(){
//It always execute but before this block if there is any statement like System.exit(0); then this block not execute.
}
3

Berücksichtigen Sie dies in einem normalen Ablauf der Ausführung (d. H. Ohne dass eine Ausnahme ausgelöst wird): Wenn die Methode nicht 'void' ist, gibt sie immer explizit etwas zurück, wird jedoch letztendlich immer ausgeführt

3
Gala101

Schließlich wird immer am Ende gerufen

wenn Sie es versuchen, führt es einen Code aus. Wenn beim Versuch etwas passiert, wird diese Ausnahme durch catch abgefangen, und Sie können ein mssg ausgeben oder einen Fehler auslösen. Anschließend wird der Block ausgeführt.

Schließlich wird normalerweise beim Bereinigen verwendet. Wenn Sie beispielsweise einen Scanner in Java verwenden, sollten Sie den Scanner wahrscheinlich schließen, da dies zu anderen Problemen führt, z. B., dass einige Dateien nicht geöffnet werden können

2
Rubin Luitel

finally-Block wird immer ausgeführt, auch wenn Sie eine return-Anweisung in den try-Block einfügen. Der finally-Block wird vor der return-Anweisung ausgeführt.

2
Sabrina

Hier sind einige Bedingungen, die einen finally-Block umgehen können:

  1. Wenn die JVM beendet wird, während der Try- oder Catch-Code ausgeführt wird, wird der finally-Block möglicherweise nicht ausgeführt. Mehr zu Sun Tutorial
  2. Normales Herunterfahren - Dies geschieht entweder, wenn der letzte Nicht-Daemon-Thread OR beendet wird, wenn Runtime.exit () ( ein gutes Blog ). Wenn ein Thread beendet wird, führt die JVM eine Bestandsaufnahme der ausgeführten Threads durch. Wenn nur noch Daemon-Threads übrig sind, wird ein ordnungsgemäßes Herunterfahren eingeleitet. Wenn die JVM anhält, werden alle verbleibenden Daemon-Threads abgebrochen. Schließlich werden Blöcke nicht ausgeführt und Stapel werden nicht abgewickelt, wenn die JVM gerade beendet wird. Daemon-Threads sollten nur sparsam verwendet werden. Nur wenige Verarbeitungsaktivitäten können ohne Bereinigung jederzeit sicher abgebrochen werden. Insbesondere ist es gefährlich, Daemon-Threads für Aufgaben zu verwenden, die eine beliebige Art von E/A ausführen können. Daemon-Threads werden am besten für "Housekeeping" -Aufgaben gespeichert, z. B. ein Hintergrund-Thread, der regelmäßig abgelaufene Einträge aus einem speicherinternen Cache entfernt ( source )

Letzter Nicht-Daemon-Thread beendet Beispiel:

public class TestDaemon {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("Is alive");
                    Thread.sleep(10);
                    // throw new RuntimeException();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                System.out.println("This will never be executed.");
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread daemon = new Thread(runnable);
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(100);
        // daemon.stop();
        System.out.println("Last non-daemon thread exits.");
    }
}

Ausgabe:

Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
0