Ar galiausiai „Java“ blokuojamas visada?

Atsižvelgiant į šį kodą, ar galiu būti visiškai įsitikinęs, kad finally blokas visada vykdomas, nepaisant to, kas something() ?

 try { something(); return success; } catch (Exception e) { return failure; } finally { System.out.println("i don't know if this will get printed out."); } 
2059 m
15 сент. davė Jonny penkiolika sep . 2008-09-15 20:43 '08 8:43 pm 2008-09-15 20:43
@ 50 atsakymų
  • 1
  • 2

Taip, finally , jis vadinamas atlikus bandomąjį arba sugavimo bloką.

Vieninteliai dalykai, kurie finally nebus vadinami:

  1. Jei skambinate „ System.exit() ;
  2. Jei JVM pirma nepavyksta;
  3. Jei JVM pasiekia begalinę kilpą (arba kitą nesibaigiančią, nesibaigiančią ataskaitą) try ar catch ;
  4. Jei OS priverstinai nutraukia JVM procesą; pavyzdžiui, „nužudyti -9“ UNIX.
  5. Jei priimančioji sistema miršta; pvz., elektros energijos triktis, aparatūros klaida, OS panika ir kt.
  6. Galiausiai, jei bloką atlieka demono gija, o visi kiti ne demono siūlai išeina, kol galiausiai bus skambinama.
2297
15 сент. atsakymą pateikė jodonnell 15 rugsėjis 2008-09-15 20:45 '08 at 8:45 pm 2008-09-15 20:45

Kodo pavyzdys:

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

Išvada:

484
15 сент. Kevino rugsėjo 15 d. Atsakymas 2008-09-15 20:59 '08 8:59 pm 2008-09-15 20:59

Be to, nors tai yra bloga praktika, jei galutiniame bloke yra grąžinimo ataskaita, ji bus didesnė už bet kokią kitą grįžimą iš įprastinio bloko. Tai reiškia, kad šis blokas grąžina klaidingą:

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

Tas pats, kuris išmeta išimtis iš galutinio bloko.

345
15 сент. Atsakyti MooBob42 Sep 15 2008-09-15 21:19 '08 9:19 val. 2008-09-15 21:19

Čia pateikiami oficialūs „Java“ kalbos specifikacijos žodžiai.

14.20.2. Atlikite bandymą pagaliau ir pabandykite sugauti

try su finally bloku vykdomas pirmą kartą paleisdami try bloką. Tada yra pasirinkimas:

  • Jei try bloko vykdymas paprastai baigiamas, [...]
  • Jei try bloko vykdymas staiga įvyksta dėl V vertės throw , [...]
  • Jei try bloko vykdymas staiga įvyksta dėl bet kokios kitos priežasties R, finally blokas įvykdomas. Tada yra pasirinkimas:
    • Jei galutinis blokas baigiamas normaliai, try staiga baigiamas dėl R.
    • Jei pagal S priežastį staiga baigia staiga blokuoti, tada try staiga įvyksta dėl S priežasties ( ir priežastis R nukrenta ).

return specifikacija iš tikrųjų tai aiškiai nurodo:

JLS 14.17 Grąžinimo operatorius

 ReturnStatement: return Expression(opt) ; 

return be Expression bando perduoti valdymą skambinančiajam ar konstruktoriui, kuriame jis yra.

return naudojant „ Expression bandymą perkelti valdymą į skambinančiojo metodą, kuriame jis yra; Expression vertė tampa metodinio skambučio verte.

Ankstesniuose aprašymuose teigiama, kad „ bandymas perduoti valdymą“, o ne tik „perdavimo kontrolė“, nes jei metode ar konstruktoriuje yra try operatorių, kurių try blokai turi return , tuomet visos šių try bus būti atliekami kaip labiausiai vidiniai išorės atžvilgiu, prieš kontrolę perkeliant į metodą arba konstruktoriaus pakvietimą. Staiga baigiant finally sąlygą gali būti sutrikdytas return inicijuotas kontrolės perdavimas.

241
25 мая '10 в 9:50 2010-05-25 09:50 atsakymas pateikiamas poligenais, nuo gegužės 25 d., 10 val., 09:50, 2010-05-25 09:50

Be kitų atsakymų, svarbu nurodyti, kad „pagaliau“ turi teisę panaikinti bet kurią išimties / grąžinimo vertę su „try..catch“ bloku. Pvz., Šis kodas grąžina 12:

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

Be to, šis metodas nesukuria išimčių:

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

Nors šis metodas yra toks:

 public static int getMonthsInYear() { try { return 12; } finally { throw new RuntimeException(); } } 
144
13 мая '10 в 10:11 2010-05-13 10:11 atsakė Eyal Schneider'ui gegužės 10 d. 10 val

Bandžiau aukščiau pateiktą pavyzdį su nedideliu pakeitimu -

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

Pirmiau nurodytas kodas išspausdinamas:

pagaliau sugrąžina trumpesnius.
2

Taip yra todėl, kad vykdant return i; i yra 2. Po to įvykdomas finally blokas, kur 12 priskiriamas i , o tada - System.out out.

Baigiantis finally blokui, try blokas grąžina 2, bet neprisideda 12, nes ši grąžinimo ataskaita dar neatliekama.

Jei derinate šį kodą „Eclipse“, pajusite, kad atlikus „ System.out , finally blokuoja System.out bloko return , jis vėl vykdomas. Bet tai ne. Ji tiesiog grąžina vertę 2.

99
17 нояб. atsakymą pateikė „ vibhash“ lapkričio 17 d 2008-11-17 19:25 '08, 19:25, 2008-11-17 19:25

Čia yra Kevino atsakymas . Svarbu žinoti, kad grąžinama išraiška vertinama finally , net jei ji grįžta po.

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

Išvada:

92
04 дек. Atsakymą pateikė WoodenKitty 04 Dec. 2013-12-04 02:36 '13 at 2:36 2013-12-04 02:36

Tai visa galutinio bloko idėja. Tai leidžia jums įsitikinti, kad darote valymą, kuris kitaip gali būti praleistas, nes, žinoma, grįžtate.

Galiausiai, jis yra naudojamas nepriklausomai nuo to, kas vyksta bandymo bloke (nebent skambinate „ System.exit(int) arba „Java“ virtualioji mašina nepradeda dėl kitos priežasties).

49
13 мая '10 в 9:19 2010-05-13 09:19 Chris Cooper atsakymas gegužės 13 d. 10 val. 9:19 2010-05-13 09:19

Logiškas būdas galvoti apie tai yra:

  • Kodą, įdėtą į galutinį bloką, reikia atlikti nepriklausomai nuo to, kas vyksta bandymo bloke.
  • Taigi, jei bandomojo bloko kodas bando grąžinti vertę arba išmesti išimtį, elementas bus patalpintas ant lentynos, kol galiausiai bus įvykdytas blokas
  • Kadangi kodas pagal galutinį bloką turi (pagal apibrėžimą) aukštą prioritetą, jis gali grąžinti arba nuleisti viską, kas jam patinka. Šiuo atveju visa, kas liko ant lentynos, yra išmesta.
  • Vienintelė išimtis yra tai, kad VM visiškai išjungiamas bandymo bloko metu. pagal „System.exit“
36
15 сент. Garth Gilmour atsakymas rugsėjo 15 d 2008-09-15 22:26 '08 10:26 pm 2008-09-15 22:26

Be to, grįžimas galiausiai išmeta išimtis. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

18
15 сент. James AN Stauffer atsakymas . 2008-09-15 22:26 '08 10:26 pm 2008-09-15 22:26

Galiausiai, jis visada vyksta, jei nėra nenormalaus programos nutraukimo (pvz., Skambinti į System.exit (0) ..). taigi jūsų sysout bus atspausdintas

17
15 сент. atsakymas pateikiamas shyam 15 sep . 2008-09-15 20:46 '08, 08:46 pm 2008-09-15 20:46

Ne, ne visada vienas išimtis //System.exit (0); kol galiausiai blokas užkerta kelią vykdymui.

  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"); } } } 
16
14 июля '13 в 2:02 2013-07-14 02:02 atsakymą pateikė Rajendra Jadi, liepos 14 d., 13 d., 2:02 2013-07-14 02:02

Galiausiai blokas visada vykdomas, jei nėra jokio nenormalaus programos nutraukimo, kurį sukelia JVM gedimas arba skambinant System.exit(0) .

Be to, bet kokia reikšmė, grąžinta iš galutinio bloko, nepaisys grąžinamos vertės, kol bus įvykdytas galutinis blokas, todėl būkite atsargūs, kai naudosite bandymą.

16
15 сент. atsakymą pateikė vartotojo9189 15 sep . 2008-09-15 21:11 '08 9:11 val. 2008-09-15 21:11

Galiausiai, visada tiesa, kad visas taškas, tik todėl, kad jis pasirodo kode po grąžinimo, nereiškia, kad jis buvo įgyvendintas. „Java“ vykdymo laikas yra atsakingas už šio kodo vykdymą, kai išeinate iš try bloko.

Pavyzdžiui, jei turite:

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

Veikimo laikas sukurs kažką panašaus:

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

Jei išmestas išimtis, bus atliktas finally blokas, o išimtis ir toliau bus propaguojama.

10
13 мая '10 в 9:18 2010-05-13 09:18 atsakė Mottii gegužės 13 d., 10 val

Taip yra dėl to, kad jūs priskyrėte reikšmę I kaip 12, bet neatšaukėte reikšmės I funkcijoje. Teisingas kodas yra toks:

 public static int test() { int i = 0; try { return i; } finally { i = 12; System.out.println("finally trumps return."); return i; } } 
9
25 мая '10 в 9:36 2010-05-25 09:36 atsakymą Wasim pateikė gegužės 25 d. 10 val. 9:36 2010-05-25 09:36

Taip, jis bus vadinamas. Tai yra visas galutinis raktinis žodis. Jei galite išeiti iš bandomojo / sugavimo bloko, galite tiesiog praleisti galutinį bloką, jis būtų toks pat, kaip „System.out.println“ įkėlimas už bandymo / sugavimo.

8
15 сент. Atsakymą pateikė Mendelt 15 rugsėjis . 2008-09-15 20:46 '08, 08:46 pm 2008-09-15 20:46

Trumpai tariant, oficialiame „Java“ dokumente (spauskite čia ) parašyta, kad:

Jei JVM išsijungia, kai vykdomas bandomasis arba sugavimo kodas, tada galutinis blokas gali būti neįgyvendintas. Taip pat, jei srauto vykdymas bandymo arba sugavimo kodais yra nutraukiamas arba nužudomas, galutinis blokas gali būti nevykdomas, net jei visa programa tęsiasi.

8
14 окт. atsakymas pateikiamas bikz05 14 okt. 2014-10-14 00:51 '14 at 0:51 2014-10-14 00:51

Kadangi galiausiai blokas visada bus iškviestas, jei neprisijungiate prie sistemos „ System.exit() (arba jei gija neveikia).

8
13 мая '10 в 9:19 2010-05-13 09:19 Atsakymą pateikė Jay Riggs gegužės 10 d. 10 val. 9:19 2010-05-13 09:19

Atsakymas paprastas TAIP .

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

IŠVADA:

 catch finally 
8
13 авг. atsakymas pateikiamas Susipažinkite su 13 rug. 2016-08-13 10:00 '16 at 10:00 2016-08-13 10:00

Taip, bus. Tik tuo atveju, jei tai neįvyks, JVM išeis arba dirbs.

7
15 янв. atsakymas pateikiamas abhig sausio 15 d 2014-01-15 01:29 '14 ne 1:29 2014-01-15 01:29

Taip, pagaliau blokas visada vykdomas. Dauguma kūrėjų naudoja šį bloką, kad uždarytų ryšį su duomenų baze, rezultato objektą, operatoriaus objektą ir taip pat naudos java miego režimu, kad grąžintų sandorį.

7
02 дек. Gautam Viradiya atsakymas 02.12 2014-12-02 15:30 '14, 15:30, 2014-12-02 15:30

Taip, bus. Nepriklausomai nuo to, kas vyksta jūsų bandymo ar sugavimo bloke, nebent kitu būdu sukeltų skambutis į System.exit () arba JVM. jei bloke (-iuose) yra grąžinimo ataskaita, jis galiausiai bus įvykdytas prieš tai, kai bus pateikta grąžinimo ataskaita.

7
16 авг. Atsakyti Karthikeyan 16 rug. 2013-08-16 15:00 '13 15:00 val. 2013-08-16 15:00

Apsvarstykite šią programą:

 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()); } private static String someString() { try { sb.append("-abc-"); return sb.toString(); } finally { sb.append("xyz"); } } } 

Pradedant nuo Java 1.8.162, aukščiau nurodytas kodų blokas suteikia tokią išėjimą:

 -abc- ---AGAIN--- -abc-xyz-abc- 

tai reiškia, kad finally išleidžiant objektus yra gera praktika, panaši į šį kodą:

 private static String someString() { StringBuilder sb = new StringBuilder(); try { sb.append("abc"); return sb.toString(); } finally { sb = null; } } 
6
30 апр. Atsakymą pateikė Samim . 2018-04-30 11:36 '18, 11:36, 2018-04-30 11:36

Kas iš tikrųjų teisinga bet kurioje kalboje ..., galiausiai, visada bus vykdoma prieš grąžinimo pareiškimą, nepriklausomai nuo to, kur ši grąža yra metodas. Jei taip nebūtų, galiausiai blokas būtų labai svarbus.

6
15 сент. Atsakymą pateikė „ Scott Dorman“ apie 15 sep. 2008-09-15 21:03 '08 at 9:03 pm 2008-09-15 21:03

Be klausimo apie grąžinimą galutiniame grąžinimo pakeitimo bandomojo bloko pakeitime, tas pats pasakytina ir apie išimtį. Galiausiai blokas, kuriantis išimtį, pakeičia grįžimo ar išimties iš bandymo bloko išimtį.

5
01 окт. Atsakymas, kurį pateikė Alex Miller Oct 01 2008-10-01 18:15 '08 18:15 pm 2008-10-01 18:15

Apsvarstykite tai įprastu vykdymo etapu (t.y. be jokių išimčių): jei metodas nėra „negaliojantis“, jis visada aiškiai grąžina kažką, bet pagaliau jis visada vykdomas

4
13 мая '10 в 14:50 2010-05-13 14:50 atsakymas duotas „ Gala101“ gegužės 13 d. 10 val

try catch - finally yra raktiniai žodžiai, naudojami naudojant išimties tvarkymo atvejį.
Kaip įprastas paaiškinimas

 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 } 

Galiausiai blokas užkerta kelią vykdymui ...

  • Kai System.exit(0);
  • Jei JVM išeina.
  • JVM klaidos
4
16 апр. Poorna Senani Gamage atsakymas . 2018-04-16 09:01 '18, 09:01 am 2018-04-16 09:01

Pridėti prie @vibhash atsakymo , nes niekas kitas atsakymas nepaaiškina, kas vyksta kintamo objekto, pvz., Žemiau, atveju.

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

Bus išvestis

 sbupdated 
4
10 апр. Pradeep Kumaresan atsakymas balandžio 10 d 2018-04-10 14:33 '18, 14:33 pm 2018-04-10 14:33

Logiškas būdas galvoti apie tai yra:

Kodą, įdėtą į galutinį bloką, reikia atlikti nepriklausomai nuo to, kas vyksta bandymo bloke.

Taigi, jei bandomojo bloko kodas bando grąžinti vertę arba išmesti išimtį, elementas bus patalpintas „ant lentynos, kol galutinis blokas gali įvykdyti. Kadangi kodas pagal galutinį bloką turi (pagal apibrėžimą) aukštą prioritetą, jis gali grįžti arba mesti viską, ką mėgsta . Šiuo atveju visa, kas liko ant lentynos, yra išmesta.

Vienintelė išimtis yra ta, kad VM visiškai išjungiamas bandymo bloko metu. pagal „System.exit“

Niekada neišmeskite išimties iš galutinio bloko

 try { someMethod(); //Throws exceptionOne } finally { cleanUp(); //If finally also threw any exception the exceptionOne will be lost forever } 

Tai gerai, jei cleanUp () niekada nesukelia jokių išimčių. Pirmiau pateiktame pavyzdyje, jei kai kuris metodas () išmeta išimtį, o galiausiai blokuoja ir išimtis, antroji išimtis bus pašalinta iš metodo, o pradinė pirmoji išimtis (teisinga priežastis) bus prarasta visam laikui. Jei kodas, kurį skambinate pagal galutinį bloką, sukelia išimtį, įsitikinkite, kad tai tvarkote arba registruojate. Niekada neleiskite išeiti iš galutinio bloko.

Iš tiesų, išeiti iš programos (arba skambinant System.exit (), arba sukeldama mirtiną klaidą, dėl kurios procesas nutraukiamas: kartais vadinamas neoficialiai „karštuoju tašku“ arba „Dr Watson“ Windows sistemoje!

Nėra nieko, kas neleistų mums įdėti bandymo / sugavimo / galo blokų (pvz., Pabandyti / galiausiai blokuoti bandomąjį / sugavimo bloką arba atvirkščiai), ir tai nėra toks neįprastas dalykas.

4
22 дек. Atsakymas pateikiamas Zia gruodžio 22 d. 2015-12-22 08:12 '15 8:12 am 2015-12-22 08:12

finally bus įvykdytas, ir tai tikrai.

finally nebus vykdomi šiais atvejais:

1 atvejis:

Kai vykdote „ System.exit() .

2 atvejis:

Jei JVM / Thread nepavyksta.

3 atvejis:

Kai vykdymas sustabdomas tarp vadovo.

4
18 дек. atsakymą pateikė Utkash Bhatt 18 d. 2014-12-18 09:36 '14 ne 9:36 2014-12-18 09:36
  • 1
  • 2

Kiti klausimai apie „ etiketes .