Vraag Wordt het uiteindelijk altijd uitgevoerd in Java?


Als ik deze code overweeg, kan dat wel absoluut zeker dat de finally blok wordt altijd uitgevoerd, ongeacht wat something() is?

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

1901
2017-09-15 17:43


oorsprong


antwoorden:


Ja, finally wordt opgeroepen na de uitvoering van de try- of catch-codeblokken.

De enige keren finally zullen niet worden genoemd zijn:

  1. Als je roept System.exit();
  2. Als de JVM als eerste crasht;
  3. Als de JVM een oneindige lus bereikt (of een andere niet-onderbreekbare, niet-beëindigende instructie) in de try of catch blok;
  4. Als het besturingssysteem het JVM-proces met geweld beëindigt; bijv. "kill -9" op UNIX.
  5. Als het hostsysteem sterft; bijv. stroomuitval, hardwarefout, OS paniek, enzovoort.
  6. Als het blok uiteindelijk wordt uitgevoerd door daemon-thread en alle andere niet-daemon-threads worden afgesloten voordat uiteindelijk wordt aangeroepen.

2114
2017-09-15 17:45



Voorbeeldcode:

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

Output:

finally trumps return. 
0

444
2017-09-15 17:59



Ook, alhoewel het een slechte oefening is, als er een return-statement is binnen het finally-blok, zal het elke andere return van het reguliere blok overtreffen. Dat wil zeggen, het volgende blok zou false opleveren:

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

Hetzelfde met uitzonderingen gooien van het laatste blok.


323
2017-09-15 18:19



Dit zijn de officiële woorden uit de Java-taalspecificatie.

14.20.2. Uitvoering van try-finally en try-catch-finally

EEN try verklaring met een finally blok wordt uitgevoerd door eerst de try blok. Dan is er een keuze:

  • Als de uitvoering van de try blok wordt normaal voltooid, [...]
  • Als de uitvoering van de try blok wordt abrupt afgesloten vanwege een throw van een waarde V, [...]
  • Als de uitvoering van de try blok wordt om een ​​andere reden abrupt voltooid R, dan de finally blok wordt uitgevoerd. Dan is er een keuze:
    • Als het laatste blok normaal wordt voltooid, dan is de try verklaring voltooit abrupt om reden R.
    • Als het finally blok wordt abrupt afgesloten voor reden S, dan de try verklaring voltooit abrupt om reden S (en reden R wordt weggegooid).

De specificatie voor return maakt dit expliciet:

JLS 14.17 De rendementsverklaring

ReturnStatement:
     return Expression(opt) ;

EEN return verklaring zonder nummer Expression  pogingen om controle over te dragen aan de invoker van de methode of constructor die het bevat.

EEN return verklaring met een Expression  pogingen om controle over te dragen aan de invoker van de methode die het bevat; de waarde van de Expression wordt de waarde van de methode-aanroeping.

De voorgaande beschrijvingen zeggen "pogingen om controle over te dragen"in plaats van alleen"draagt ​​controle over"want als die er zijn try verklaringen binnen de methode of constructor waarvan try blokken bevatten de return verklaring en vervolgens elke finally clausules daarvan try statements worden uitgevoerd, op volgorde van binnen naar buiten, voordat de controle wordt overgedragen aan de invoker van de methode of constructor. Abrupte voltooiing van een finally clausule kan de overdracht van de controle geïnitieerd door a blokkeren return uitspraak.


229
2018-05-25 06:50



Naast de andere antwoorden is het belangrijk erop te wijzen dat 'finally' het recht heeft om elke uitzondering / geretourneerde waarde te overschrijven door het try..catch-blok. De volgende code retourneert bijvoorbeeld 12:

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

Op dezelfde manier werpt de volgende methode geen uitzondering:

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

Hoewel de volgende methode het wel doet:

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

134
2018-05-13 07:11



Ik probeerde het bovenstaande voorbeeld met een kleine wijziging-

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

De bovenstaande code uitgangen:

tenslotte troef de terugkeer.
  2

Dit komt omdat wanneer return i; is geëxecuteerd i heeft een waarde 2. Hierna de finally blok wordt uitgevoerd waar 12 is toegewezen aan i en dan System.out uit wordt uitgevoerd.

Na het uitvoeren van de finally blokkeer de try blok retourneert 2, in plaats van 12 terug te sturen, omdat deze retourinstructie niet opnieuw wordt uitgevoerd.

Als u deze code in Eclipse gaat debuggen, krijgt u een gevoel dat na het uitvoeren System.out van finally blokkeer de return uitdrukking van try blok wordt opnieuw uitgevoerd. Maar dit is niet het geval. Het geeft simpelweg de waarde 2 terug.


88
2017-11-17 16:25



Hier is een uitwerking van Kevin's antwoord. Het is belangrijk om te weten dat de uit te drukken uitdrukking eerder is geëvalueerd finally, zelfs als het na wordt teruggegeven.

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

Output:

X
finally trumps return... sort of
0

80
2017-12-03 23:36