Frage

In Anbetracht dieser Code, kann ich sein absolut sicher , dass der finally Block führt immer, egal 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");
}
War es hilfreich?

Lösung

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

Das einzige Mal finally wird nicht aufgerufen werden:

  1. Wenn Sie rufen System.exit()
  2. Wenn die JVM stürzt erste
  3. Wenn die JVM erreichen eine Endlosschleife (oder ein anderer nicht-unterbrechbare, nicht abbreche statement) im try oder catch Block
  4. Wenn das Betriebssystem gewaltsam den JVM-Prozess endet; z.B. kill -9 <pid> auf UNIX
  5. Wenn das Host-System stirbt; beispielsweise Stromausfall, Hardware-Fehler, O Panik, et cetera
  6. Wenn der finally Block wird von einem Dämon-Thread und alle anderen Nicht-Daemon-Threads Ausgang ausgeführt werden, bevor finally genannt wird

Andere Tipps

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

Auch, obwohl es schlechte Praxis, wenn es eine return-Anweisung innerhalb des finally-Block ist, wird es Trumpf andere Rückkehr aus dem regulären Block. Das heißt, der folgende Block würde return false:

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

Das Gleiche gilt für das Werfen Ausnahme von der finally-Block.

Hier sind die offiziellen Worte aus der Java Language Specification.

14.20.2. Durchführung von Versuchen-finally und try-catch-finally

  

Eine try Anweisung mit einem finally Block wird durch erste Ausführung des try Block ausgeführt. Dann gibt es eine Auswahl:

     
      
  • Wenn die Ausführung des try Block schließt normalerweise, [...]
  •   
  • Wenn die Ausführung des try Block wegen eines throw eines Wertes abrupt beendet V [...]
  •   
  • Wenn die Ausführung des try Block abrupt aus einem anderen Grund beendet R , dann wird der finally Block ausgeführt. Dann gibt es eine Auswahl:      
        
    • Wenn der finally-Block normal abgeschlossen ist, dann wird die try Anweisung abgeschlossen abrupt Grund R .
    •   
    • Wenn der finally Block abrupt Grund beendet S , dann schließt die try Anweisung abrupt Grund S ( und Vernunft R verworfen ).
    •   
  •   

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

JLS 14.17 Die return-Anweisung

ReturnStatement:
     return Expression(opt) ;
     

A return Anweisung ohne Expression Versuche die Steuerung an den Aufrufer des Verfahrens oder den Konstruktor zu übertragen, die sie enthält.

     

A return Anweisung mit einer Expression Versuche die Steuerung an den Aufrufer der Methode zu übertragen, die sie enthält; der Wert der Expression den Wert des Methodenaufrufes wird.

     

Die vorstehenden Beschreibungen sagen " Versuche Kontrolle übertragen " und nicht nur " wechselt die Steuerung ", weil, wenn es irgendwelche try Aussagen innerhalb der Methode oder deren Konstruktor try blockiert die return Anweisung enthalten, dann werden alle Klauseln finally dieser try Anweisungen ausgeführt werden, um die innerste, zu den äußersten, bevor die Steuerung an den Aufrufer des Verfahrens oder der Konstruktor übertragen wird. Abrupte Abschluss einer finally-Klausel kann die Übertragung der Kontrolle unterbricht durch eine return Anweisung eingeleitet.

Zusätzlich zu den anderen Antworten, ist es wichtig, darauf hinzuweisen, dass ‚endlich‘ das Recht hat, jede Ausnahme / Rückgabewert vom try..catch Block außer Kraft zu setzen. Zum Beispiel kann der folgende Code gibt 12:

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

In ähnlicher Weise kann das folgende Verfahren nicht eine Ausnahme:

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

Während die folgende Methode es nicht werfen:

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

Ich habe versucht, das obige Beispiel mit geringfügiger Änderung -

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 oben genannten Code-Ausgänge:

  

schließlich Trümpfe Rückkehr.
  2

Dies liegt daran, wenn return i; ausgeführt i einen Wert hat, 2. Danach wird der finally Block ausgeführt wird, in dem 12 zugeordnet ist i und dann System.out aus ausgeführt wird.

Nach dem Ausführen des finally blockiert den try Block 2 zurück, anstatt 12 zurückkehrt, weil diese Anweisung return wieder nicht ausgeführt wird.

Wenn Sie diesen Code in Eclipse debuggen werden dann werden Sie ein Gefühl bekommen, dass System.out von finally Block der return Anweisung von try Block nach der Ausführung wieder ausgeführt wird. Aber dies ist nicht der Fall. Es gibt einfach den Wert 2.

Hier ist eine Ausarbeitung von Kevins Antwort . Es ist wichtig zu wissen, dass der Ausdruck zurückgegeben werden, bevor finally ausgewertet wird, auch wenn es nach zurückgeführt 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

Das ist die ganze Idee eines schließlich blockieren. Damit können Sie sicherstellen, dass Sie tun Bereinigungen, die sonst übersprungen werden könnten, weil Sie zurückkommen, unter anderem natürlich.

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

Ein logischer Weg, um dies zu denken ist:

  1. -Code in einem finally-Block platziert ausgeführt werden muss Was geschieht innerhalb des try-Block
  2. Also, wenn Code im try-Block versucht, einen Wert zurückgeben oder eine Ausnahme der Artikel werfen wird ‚auf dem Regal‘ gesetzt, bis der schließlich Block ausführen kann
  3. Da Code im finally-Block (per Definition) hat eine hohe Priorität kann es zurückgeben oder werfen, was es will. In diesem Fall etwas links ‚auf dem Regal‘ verworfen.
  4. Die einzige Ausnahme ist, wenn der VM vollständig Block während des try heruntergefahren z von 'System.exit'

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

schließlich wird immer dann ausgeführt, es sei denn, es gibt Unerwarteter Programmabbruch (wie der Aufruf System.exit (0) ..). so, erhalten Ihre sysout gedruckt

Der finally-Block wird immer dann ausgeführt, es sei denn, es gibt Unerwarteter Programmabbruch, entweder aus einer JVM abstürzen oder von einem Aufruf System.exit(0).

Hinzu kommt, dass, kehrte jeder beliebige Wert innerhalb des finally-Block wird den Wert zurück vor der Ausführung der finally-Block, so vorsichtig sein, Überprüfung aller Ausstiegspunkte außer Kraft setzen, wenn versuchen, mit schließlich.

Nein, nicht immer ein Ausnahmefall ist // System.exit (0); bevor der finally-Block ausgeführt schließlich wird verhindert.

  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");
        }
    }
}

Schließlich ist immer laufen, das ist der springende Punkt, nur weil es in dem Code nach der Rückkehr erscheint, bedeutet nicht, dass das ist, wie es umgesetzt werden. Die Java-Laufzeit hat die Aufgabe, diesen Code auszuführen, wenn der try Block verlassen wird.

Zum Beispiel, wenn Sie die folgenden Schritte aus:

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

Die Laufzeit wird in etwa so erzeugen:

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

Wenn eine abgefangene Ausnahme der finally Block geworfen wird, läuft und die Ausnahme ausbreitende fortsetzen wird.

Das ist, weil Sie den Wert von i als 12 zugewiesen, aber den Wert von i auf die Funktion nicht zurück. 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;
    }
}

Da ein finally-Block wird immer dann aufgerufen werden, es sei denn, Sie rufen System.exit() (oder der Faden stürzt ab).

  

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

Ja, es wird erhalten genannt. Das ist der springende Punkt ein schließlich Schlüsselwort zu haben. Wenn springen könnte aus dem try / catch-Block nur die überspringen schließlich war blockiert es das gleiche wie das System.out.println außerhalb des try / catch setzen.

Kurz und bündig, in der offiziellen Java Dokumentation (Klicken Sie hier ), es steht geschrieben, dass -

  

Wenn die JVM beendet, während der Versuch oder Fang Code ausgeführt wird, dann   der finally-Block nicht ausgeführt werden kann. Ebenso, wenn der Thread ausführt   der Versuch oder Fang Code unterbrochen oder getötet wird, kann der finally-Block   weiterhin nicht ausführen, obwohl als Ganzes die Anwendung.

Ja, schließlich wird Block immer ausgeführt werden. Die meisten Entwickler verwenden diesen Block die Schließung der Datenbankverbindung, resultset Objekt, Statement-Objekt und auch in die Java verwendet wintern die Transaktion rückgängig zu machen.

Ja, wird es. Egal, was in Ihrem Versuch oder catch-Block passiert, wenn nichts anderes System.exit () aufgerufen oder JVM abgestürzt. wenn es eine return-Anweisung in dem Block (n) ist, wird schließlich ausgeführt vor dieser return-Anweisung.

Ja, es wird. Nur Fall wird es nicht JVM-Exits oder Abstürze

ist

Sie sich 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");
        }
    }
}

Wie von Java 1.8.162, der obige Code-Block gibt die folgende Ausgabe:

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

Dies bedeutet, dass finally mit Objekten befreien eine gute Praxis, wie der folgende Code ist:

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.
    }
}

Das ist tatsächlich wahr in jeder Sprache ... endlich wird immer vor einer return-Anweisung ausführen, unabhängig davon, wo die Rückkehr in dem Verfahren Körper. Wenn das nicht der Fall war, würde der finally-Block nicht viel Bedeutung haben.

finally wird ausgeführt, und das ist sicher.

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

Fall 1:

Wenn Sie System.exit() ausgeführt werden.

Fall 2:

Wenn Sie Ihre JVM / Thema stürzt ab.

Fall 3:

Wenn Sie Ihre Ausführung wird zwischen manuell gestoppt in.

Wenn Sie keine Ausnahme behandeln, bevor das Programm beendet wird, führt JVM schließlich blockieren. Es wird nicht nur ausgeführt, wenn die normale Ausführung des Programms bedeutet die Beendigung des Programms aufgrund dieser folgenden Gründen fehlschlagen ..

  1. Durch einen fatalen Fehler verursacht, dass der Prozess verursacht abzubrechen.

  2. Beendigung des Programms aufgrund Speicher beschädigt.

  3. Mit dem Aufruf System.exit ()

  4. Wenn das Programm in der Unendlichkeit Schleife geht.

Ja, weil keine Steueranweisung kann verhindern, dass finally ausgeführt wird.

Hier ist ein Referenzbeispiel, in dem alle Codeblocks 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 Variante unten wird return x; übersprungen werden. Das Ergebnis wird 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, natürlich, verfolgen dessen Status. Dieses Beispiel gibt eine Referenz mit value = 4:

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
    }
}

try- catch- finally sind die Schlüsselwörter für die Ausnahmebehandlung Fall verwenden.
Wie normale explanotory

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 Ausführen ...

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

Zusätzlich zu @ vibhash Antwort wie keine andere Antwort erklärt, was, wie die in dem Fall ein veränderlichen Objekts geschieht unter .

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 ");
    }
}

Will Ausgang

sbupdated 

Ich habe 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 auf Wartezustand für immer sein wird, wird daher schließlich nie, aufgerufen werden

so Konsolenausgabe wird nicht gedruckt string: after wait() oder finally

Vereinbarte mit @Stephen C ist das obige Beispiel eine der 3. Fall Erwähnung hier :

Hinzufügen mehr solche Endlosschleife Mö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 stürzt ersten

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 abstürzen Sie eine JVM

Fall 6:. Wenn schließlich Block von Daemon-Thread und alle anderen Nicht-Daemon-Threads Ausgang ausgeführt werden wird, bevor sie schließlich genannt wird

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("-------------------------------------------------");
    }
}

Ausgang: Dies gilt nicht "endlich" drucken, die "Finally-Block" in "Dämon-Thread" impliziert, wurde nicht ausgeführt

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top