අවසාන වශයෙන් අවහිර කිරීම සැමවිටම ජාවා හි ක්‍රියාත්මක වේද?


2386

මෙම කේතය සලකා බැලීමේදී, කුමක් වුවත්, වාරණය සැමවිටම ක්‍රියාත්මක වන බව මට සහතික විය හැකිද?finallysomething()

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

475
එය එසේ නොවේ නම්, probablyඒ වෙනුවට මූලික පදය නම් කළ යුතුය .
දහවල් සිල්ක්




27
In බිනෝයි බාබු, අවසන් කරන්නා ! = finally; finalizer == finalize()ක්‍රමය.
jaco0646

Answers:


2702

ඔව්, හෝ finallyක්‍රියාත්මක කිරීමෙන් පසුව කැඳවනු ලැබේtrycatch කේත කොටස් .

finallyනොකියන එකම වේලාවන් වන්නේ:

  1. ඔබ ආයාචනා කරන්නේ නම් System.exit()
  2. ඔබ ආයාචනා කරන්නේ නම් Runtime.getRuntime().halt(exitStatus)
  3. ජේවීඑම් පළමුව බිඳ වැටේ නම්
  4. ජේවීඑම් අසීමිත පුඩුවක් කරා ළඟා වුවහොත් (හෝ වෙනත් බාධා කළ නොහැකි, අවසන් නොවන ප්‍රකාශයක්) tryහෝcatch බ්ලොක් එකේ
  5. මෙහෙයුම් පද්ධතිය JVM ක්‍රියාවලිය බලහත්කාරයෙන් අවසන් කරන්නේ නම්; උදා:kill -9 <pid> යුනික්ස් මත
  6. ධාරක පද්ධතිය මිය ගියහොත්; උදා: විදුලිය ඇණහිටීම, දෘඩාංග දෝෂය, මෙහෙයුම් පද්ධතිය භීතිකාව සහ වෙනත් ය
  7. finallyඅවහිරය ඩීමන් නූල් මඟින් ක්‍රියාත්මක කිරීමට යන්නේ නම් සහ ඊට පෙර පිටවන අනෙකුත් ඩීමන් නොවන නූල් සියල්ලම finallyහැඳින්වේ

44
ඇත්ත වශයෙන්ම අවහිර කිරීම ක්‍රියාත්මක thread.stop()කිරීම වලක්වනු නොලැබේ finally.
Piotr Findeisen

182
කොහොමද අපි කියන්නේ finallyබ්ලොක් එක බ්ලොක් එකෙන් පසුව කැඳවනු ඇති බවත් try, පාලනය පහත ප්‍රකාශ වලට යොමු වීමට පෙර . එය අසීමිත ලූපයක් සම්බන්ධ උත්සාහක වාරණයට අනුකූල වන අතර එම නිසා අවසාන වාරණය කිසි විටෙකත් සත්‍ය වශයෙන්ම ආයාචනා නොකෙරේ.
ඇන්ඩ්‍රෙජ් ඩොයිල්

9
තවත් අවස්ථාවක් තිබේ, අපි කැදැලි අත්හදා බැලීම්-අවසාන වාරණ භාවිතා කරන විට
රුහුන්ග්‍රි

7
ඩීමන් නූල් මගින් විසි කරන විට අවසාන වශයෙන් වාරණය නොකෙරේ.
අම්රිෂ් පාණ්ඩේ

14
In බිනෝයි බාබු - එය අවසාන කාරකය ගැන මිස අවසාන වශයෙන් අවහිර
නොකරයි

568

උදාහරණ කේතය:

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

ප්‍රතිදානය:

finally trumps return. 
0

18
FYI: finally-Clause හි ප්‍රකාශය ප්‍රතිස්ථාපනය return 2;කිරීමට අවසර නැත යන කාරණයට අමතරව C # හි හැසිරීම සමාන වේ (සම්පාදක-දෝෂය).
ඇලෙක්සැන්ඩර් පචා

15
දැනුවත් විය යුතු වැදගත් විස්තරයක් මෙන්න: stackoverflow.com/a/20363941/2684342
WoodenKitty

19
අවසාන වාරණය තුළම ඔබට ආපසු ප්‍රකාශයක් එකතු කළ හැකිය, එය පෙර ප්‍රතිලාභ අගය අභිබවා යයි. මෙය ද පාලනය කළ නොහැකි ව්‍යතිරේකයන් ඉන්ද්‍රජාලිකව බැහැර කරයි. එම අවස්ථාවේදී, ඔබේ කේතය නැවත සකස් කිරීම ගැන සලකා බැලිය යුතුය.
Zyl

8
අවසානයේදී තුරුම්පු නැවත පැමිණෙන බව එය සැබවින්ම ඔප්පු නොකරයි. ප්‍රතිලාභ අගය ඇමතුම් කේතයෙන් මුද්‍රණය කෙරේ. බොහෝ දේ ඔප්පු කරන බවක් නොපෙනේ.
ට්‍රිම්ටාබ්

20
කණගාටුයි, නමුත් මෙය නිරූපණයක් නොවේ. මෙම උදාහරණය සෑම ජාවා වේදිකාවකම සෑම විටම මේ ආකාරයෙන් හැසිරෙන බවත්, ඒ හා සමාන උදාහරණ සෑම විටම මේ ආකාරයෙන් හැසිරෙන බවත් ඔබට පෙන්විය හැකි නම් එය සාක්ෂියක් පමණි.
ස්ටීවන් සී

391

එසේම, එය නරක පුරුද්දක් වුවද, අවසාන වාරණය තුළ ආපසු ප්‍රකාශයක් තිබේ නම්, එය සාමාන්‍ය වාරණයෙන් වෙනත් ප්‍රතිලාභයක් තුරන් කරනු ඇත. එනම්, පහත දැක්වෙන කොටස වැරදියි:

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

අවසාන වාරණයෙන් ව්‍යතිරේකයන් විසි කිරීමත් එසේමයි.


95
මෙය ඇත්තෙන්ම නරක පුරුද්දකි. එය නරක වීමට හේතුව පිළිබඳ වැඩි විස්තර සඳහා stackoverflow.com/questions/48088/… බලන්න .
ජෝන් මේගර්

23
එකඟ විය. අවසාන වශයෙන් {} උත්සාහය තුළට විසි කරන ඕනෑම ව්‍යතිරේකයක් නොසලකා හරියි}}. භයංකාර!
neu242

8
@ domicbri7 එය වඩා හොඳ පුහුණුවක් යැයි ඔබ සිතන්නේ ඇයි? ශ්‍රිතය / ක්‍රමය අවලංගු වූ විට එය වෙනස් විය යුත්තේ ඇයි?
corsiKa

8
මගේ C ++ කේත වල මම ගොටෝ භාවිතා නොකරමි. මම හිතන්නේ බහුවිධ ප්‍රතිලාභ කියවීම දුෂ්කර වන අතර නිදොස් කිරීම වඩාත් අපහසු වේ (ඇත්ත වශයෙන්ම සරල අවස්ථාවන්හිදී එය අදාළ නොවේ). මම හිතන්නේ එය හුදෙක් පුද්ගල මනාපයක් වන අතර අවසානයේ ඔබට මෙම ක්‍රම දෙකම භාවිතා කර එකම දේ සාක්ෂාත් කරගත හැකිය
domicbri7

16
කිසියම් සුවිශේෂී සිද්ධියක් සිදු වූ විට මම ප්‍රතිලාභ ගණනාවක් භාවිතා කිරීමට නැඹුරු වෙමි. (ඉදිරියට නොයෑමට හේතුවක් තිබේ නම්) නැවත පැමිණීම වැනි;
iHearGeoff

257

ජාවා භාෂා පිරිවිතරයේ නිල වචන මෙන්න.

14.20.2. උත්සාහ-අවසානයේ සහ උත්සාහ-අල්ලා-අවසානයේ ක්‍රියාත්මක කිරීම

tryසමඟ ප්රකාශයක් finallyවාරණ පළමුව සිදු කිරීමෙන් ක්රියාත්මක වන tryවාරණ. එවිට තේරීමක් තිබේ:

  • tryවාරණය ක්‍රියාත්මක කිරීම සාමාන්‍යයෙන් සම්පූර්ණ වුවහොත් , [...]
  • V අගය tryනිසා වාරණය ක්‍රියාත්මක කිරීම හදිසියේම සම්පූර්ණ වුවහොත් , [...]throw
  • Rtry වෙනත් හේතුවක් නිසා වාරණය ක්‍රියාත්මක කිරීම හදිසියේම සම්පූර්ණ වුවහොත් , වාරණය ක්‍රියාත්මක වේ. එවිට තේරීමක් තිබේ:finally
    • අවසාන වාරණය සාමාන්‍යයෙන් සම්පුර්ණ වුවහොත්, tryප්‍රකාශය R හේතුව නිසා හදිසියේම සම්පූර්ණ වේ .
    • Sfinally හේතුව නිසා වාරණය හදිසියේම සම්පූර්ණ වුවහොත් , ප්‍රකාශය S හේතුව නිසා හදිසියේම සම්පූර්ණ වේtry ( හා හේතුව ආර් ඉවත්කෙරෙනු ඇත ).

returnඇත්ත වශයෙන්ම සඳහා පිරිවිතර මෙය පැහැදිලි කරයි:

JLS 14.17 ආපසු ප්‍රකාශය

ReturnStatement:
     return Expression(opt) ;

return සඳහා කිසිදු ප්රකාශයක් Expression උත්සාහයන් එය අඩංගු වන බව මෙම ක්රමය හෝ ඉදිකිරීමටත් වන invoker කිරීමට පාලනය මාරු කිරීමට.

return සමග ප්රකාශයක් Expression උත්සාහයන් එය අඩංගු වන බව ක්රමය පිළිබඳව invoker කිරීමට පාලනය මාරු කිරීම; මෙම වටිනාකම Expressionක්රමය පිහිට පැතීමක් වටිනාකම බවට පත් වෙයි.

පූර්ව විස්තර වලින් කියැවෙන්නේ “ පාලනය මාරු කිරීම ” වෙනුවට “ පාලනය මාරු කිරීමට උත්සාහ කිරීම ” මන්ද යත් try, ක්‍රමවේදය තුළ හෝ ප්‍රකාශකයාගේ ප්‍රකාශයන් tryඅඩංගු ඉදිකිරීම්කරු තුළ කිසියම් ප්‍රකාශයක් තිබේ returnනම් finally, එම tryප්‍රකාශවල ඕනෑම වගන්තියක් ක්‍රියාත්මක වන අතර, අනුපිළිවෙලින්, අභ්‍යන්තරයෙන් පිටත සිට , පාලනය ක්‍රමයේ හෝ ඉදිකිරීම්කරුගේ ආයාචකයා වෙත මාරු කිරීමට පෙර. finallyවගන්තියක් හදිසියේම සම්පූර්ණ කිරීමෙන් returnප්‍රකාශයක් මඟින් ආරම්භ කරන ලද පාලනය මාරු කිරීම කඩාකප්පල් විය හැකිය .


164

අනෙක් ප්‍රතිචාර වලට අමතරව, උත්සාහය..කැච් බ්ලොක් මඟින් ඕනෑම ව්‍යතිරේකයක් / ආපසු ලබා දුන් අගයක් අභිබවා යාමට 'අවසාන වශයෙන්' අයිතියක් ඇති බව පෙන්වා දීම වැදගත්ය. උදාහරණයක් ලෙස, පහත කේතය 12 ලබා දෙයි:

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

ඒ හා සමානව, පහත දැක්වෙන ක්රමය ව්යතිරේකයක් විසි නොකරයි:

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

පහත දැක්වෙන ක්‍රමය එය විසි කරන අතර:

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

63
අවසාන කොටසේ නැවත ප්‍රකාශයක් තිබීම ඇත්තෙන්ම භයානක වීමට හේතුව මැද නඩුව බව සැලකිල්ලට ගත යුතුය (එය විසි කළ හැකි ඕනෑම දෙයක් සැඟවිය හැක).
ඩිමිට්‍රිස් ඇන්ඩෘ

2
කවුද නැත වූ surpressed අවශ්ය OutOfMemoryError? ;)
පුනරාවර්තන එක්සෙප්ෂන්එක්සෙප්ෂන්

මම එය පරීක්‍ෂා කළ අතර එය එවැනි දෝෂයක් මැඩපවත්වයි (යිප්ස්!). මා එය සම්පාදනය කරන විට එය අනතුරු ඇඟවීමක් ද ජනනය කරයි (ඔව්!). ඔබ ආපසු විචල්ය නිර්වචනය හා පසුව භාවිතා, එය වටා වැඩ කළ හැකි return retVal පසු එම finallyපාඨමාලාව ඔබ වෙනත් ව්යතිරේක යටපත් කරන කේතය එසේ තේරුමක් නැති නිසා උපකල්පනය වුවත්, වාරණ.
මාර්ටන් බොඩෙව්ස්

120

මම ඉහත උදාහරණය සුළු වෙනස් කිරීමකින් උත්සාහ කළෙමි-

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

ඉහත කේත ප්‍රතිදානයන්:

අවසානයේ තුරුම්පුව නැවත පැමිණේ.
2

මෙයට හේතුව return i;වන්නේ ක්‍රියාත්මක කරන iවිට අගය 2 ක් තිබීමයි. මෙයින් පසු finallyවාරණය 12 ක් පවරා ඇති iඅතර System.outපිටතට ක්‍රියාත්මක වේ.

finallyවාරණය ක්‍රියාත්මක කිරීමෙන් පසුtry 12 ක් ආපසු ලබා දෙනවාට වඩා 2 ක් ලබා දෙයි.

ඔබ මෙම කේතය සූර්යග්‍රහණයෙන් නිදොස්කරණය කරන්නේ නම් System.out, finallyවාරණය ක්‍රියාත්මක කිරීමෙන් පසු වාරණ returnප්‍රකාශය tryනැවත ක්‍රියාත්මක වන බවට ඔබට හැඟීමක් ඇති වේ. නමුත් මෙය එසේ නොවේ. එය සරලවම 2 අගය ලබා දෙයි.


10
මෙම උදාහරණය නියමයි, එය දුසිම් ගණනක් සඳහන් කර නැති දෙයක් එකතු කරයි. මම හිතන්නේ යන්තම් ඕනෑම සංවර්ධකයෙක් මෙය දැන ගනීවි.
බලාපොරොත්තුවෙන්

4
iප්‍රාථමික නොව පූර්ණ සංඛ්‍යා වස්තුවක් නම් කුමක් කළ යුතුද?
යම්චා

මෙම නඩුව තේරුම් ගැනීමට මට අපහසුය. docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 මෙසේ පවසයි, “ප්‍රකාශනයක් සහිත ආපසු ප්‍රකාශයක් මඟින් ක්‍රමවේදය හෝ ලැම්බා ශරීරය අඩංගු ඉන්වොයිසර් වෙත පාලනය මාරු කිරීමට උත්සාහ කරයි. එය .... ප්‍රකාශනය ඇගයීම සාමාන්‍යයෙන් සම්පුර්ණ වුවහොත් V අගයක් නිපදවයි .. "මෙම ප්‍රකාශයෙන් මට අනුමාන කළ හැකි දෙය නම්- V අගය තක්සේරු කළ පසු නැවත ප්‍රකාශනය නැවත ඇගයීමට ලක් නොකරන බව පෙනේ. ආපසු ලබා දුන් වටිනාකමට බලපාන්නේ නැත, මාව නිවැරදි කරන්න.
meexplorer

නමුත් මේ සම්බන්ධයෙන් මට කිසිදු සාක්ෂියක් හමු නොවීය, නැවත පැමිණීම ප්‍රකාශනය නැවත ඇගයීමට ලක් නොකරන බව සඳහන් කර ඇත.
meexplorer

1
@meexplorer ටිකක් ප්‍රමාදයි, නමුත් එය JLS 14.20.2 හි විස්තර කර ඇත . උත්සාහ කිරීම-අවසානයේ සහ උත්සාහ-අල්ලා-අවසානයේ ක්‍රියාත්මක කිරීම - ටිකක් සංකීර්ණ වචන වලින්, 14.17. ආපසු ප්‍රකාශය ද කියවිය යුතුය
පරිශීලක 85421

117

මෙන්න කෙවින්ගේ පිළිතුරේ විස්තාරණයකි . ආපසු ලබා දිය යුතු ප්‍රකාශනය පෙර ඇගයීමට ලක් කර ඇති බව දැන ගැනීම වැදගත්ය finally.

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

ප්‍රතිදානය:

X
finally trumps return... sort of
0

8
දැනගැනීම වැදගත්.
අමිනාදව් ග්ලික්ස්ටයින්

දැන ගැනීමට ලැබීම සතුටක් මෙන්ම අර්ථවත් කරයි. ප්‍රතිලාභයේ වටිනාකම සැබවින්ම ආපසු ලබා දීමෙන් පසුව ලැබෙන බව පෙනේ finally. ප්‍රතිලාභ අගය ගණනය කිරීම (printX() මෙහි) තවමත් එයට පෙර පැමිණේ.
ඇල්බට්

නෑ. ඉහත කේතය ප්‍රතිස්ථාපනය කළ යුතුයSystem.out.println("finally trumps return... sort of"); සමගSystem.out.print("finally trumps return in try"); return 42;
Pacerier

54

අවසාන වශයෙන් අවහිර කිරීම පිළිබඳ සම්පූර්ණ අදහස එයයි. ඇත්ත වශයෙන්ම ඔබ නැවත පැමිණීම නිසා වෙනත් ආකාරයකින් මඟ හැරිය හැකි පිරිසිදු කිරීම් සිදු කිරීමට එය ඔබට ඉඩ දෙයි.

උත්සාහක කොටසෙහි කුමක් සිදුවේද යන්න නොසලකා අවසාන වශයෙන් අමතනු ලැබේ ( ඔබ ඇමතුමක් හෝ ජාවා අතථ්‍ය යන්ත්‍රය වෙනත් හේතුවක් නිසා ඉවත් නොවන්නේ නම්System.exit(int) ).


එය අතිශය දුර්වල පිළිතුරකි. stackoverflow.com/a/65049/715269
ගැන්ග්නස්

42

මේ ගැන සිතීමට තාර්කික ක්‍රමයක් නම්:

  1. අවසාන කොටසක තබා ඇති කේතය ක්‍රියාත්මක කළ යුතුය උත්සාහක කොටස තුළ සිදුවන ඕනෑම දෙයක්
  2. එබැවින් උත්සාහක වාරණයේ ඇති කේතයක් වටිනාකමක් ලබා දීමට හෝ ව්‍යතිරේකයක් විසි කිරීමට උත්සාහ කරන්නේ නම්, අවසාන වාරණය ක්‍රියාත්මක වන තෙක් අයිතමය 'රාක්කයේ' තබා ඇත.
  3. අවසාන කොටසේ කේතයට (අර්ථ දැක්වීම අනුව) ඉහළ ප්‍රමුඛතාවයක් ඇති බැවින් එයට නැවත පැමිණීමට හෝ කැමති දෙයක් විසි කිරීමට හැකිය. 'රාක්කයේ' ඉතිරිව ඇති ඕනෑම දෙයක් ඉවතලනු ලැබේ.
  4. මෙයට ඇති එකම ව්‍යතිරේකය වන්නේ උත්සාහක වාරණයේදී VM සම්පූර්ණයෙන්ම වසා දැමුවහොත් උදා. 'System.exit'

10
මෙය හුදෙක් "ඒ ගැන සිතීමට තාර්කික ක්‍රමයක්" ද නැතිනම් පිරිවිතරයන්ට අනුව වැඩ කිරීමට අවසාන වාරණය අදහස් කරන්නේ කෙසේද? සූර්ය සම්පතක් සඳහා සබැඳියක් මෙහි ඉතා රසවත් වනු ඇත.
මාටියාස්

21

අසාමාන්‍ය වැඩසටහන් අවසන් කිරීමක් නොමැති නම් (System.exit (0) අමතන්න වැනි) අවසානයේදී සෑම විටම ක්‍රියාත්මක වේ. ඉතින්, ඔබේ සයිස්අවුට් මුද්‍රණය වේ



18

ජේවීඑම් බිඳවැටීමක හෝ ඇමතුමක ප්‍රති ing ලයක් ලෙස අසාමාන්‍ය වැඩසටහන් අවසන් කිරීමක් සිදු නොවන්නේ නම් අවසාන වාරණය සැමවිටම ක්‍රියාත්මක වේ System.exit(0).

ඊට ඉහළින්, අවසාන වාරණය තුළ සිට ආපසු ලබා දෙන ඕනෑම අගයක් අවසාන වාරණය ක්‍රියාත්මක කිරීමට පෙර ආපසු ලබා දුන් අගය ඉක්මවා යනු ඇත, එබැවින් අවසාන වශයෙන් උත්සාහ කිරීම භාවිතා කරන විට සියලු පිටවීමේ ස්ථාන පරීක්ෂා කිරීමට ප්‍රවේශම් වන්න.


18

නැත, සෑම විටම එක් ව්‍යතිරේක නඩුවක් නොවේ // System.exit (0); අවසාන වාරණය අවසානයේදී ක්‍රියාත්මක කිරීම වළක්වයි.

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

System.exit () ලෙස ඔබ කිසි විටෙකත් නොකිය යුතු එක් හේතුවක් එයයි ...
ෆ්‍රාන්ස් ඩී.

13

අවසාන වශයෙන් සෑම විටම ක්‍රියාත්මක වන්නේ එය සමස්ත ලක්ෂ්‍යයයි, නැවත පැමිණීමෙන් පසු එය කේතයේ දිස්වන නිසා එය ක්‍රියාත්මක වන්නේ කෙසේදැයි නොවේ. tryබ්ලොක් එකෙන් පිටවන විට මෙම කේතය ක්‍රියාත්මක කිරීමේ වගකීම ජාවා ධාවන කාලයට ඇත .

උදාහරණයක් ලෙස ඔබට පහත සඳහන් දෑ තිබේ නම්:

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

ධාවන කාලය මෙවැනි දෙයක් ජනනය කරනු ඇත:

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

හඳුනා නොගත් ව්‍යතිරේකයක් විසි finallyකළහොත් වාරණය ක්‍රියාත්මක වන අතර ව්‍යතිරේකය දිගටම ප්‍රචාරණය වේ.


11

මෙයට හේතුව ඔබ i හි අගය 12 ලෙස පවරා ඇති නමුත් i හි අගය ශ්‍රිතයට ලබා නොදීමයි. නිවැරදි කේතය පහත පරිදි වේ:

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

10

ඔබ ඇමතුමක් ලබා නොදුනහොත් System.exit()(හෝ නූල් කඩාවැටෙන්නේ නම්) අවසාන වාරණය සැමවිටම කැඳවනු ඇත.


10

සංක්ෂිප්තව, නිල ජාවා ප්‍රලේඛනයේ ( මෙහි ක්ලික් කරන්න ), එය ලියා ඇත්තේ -

උත්සාහක හෝ අල්ලා ගැනීමේ කේතය ක්‍රියාත්මක වන අතරතුර JVM පිටවන්නේ නම්, අවසාන වාරණය ක්‍රියාත්මක නොවනු ඇත. ඒ හා සමානව, උත්සාහක හෝ අල්ලා ගැනීමේ කේතය ක්‍රියාත්මක කරන නූල් බාධා හෝ killed ාතනය වී ඇත්නම්, සමස්තයක් ලෙස යෙදුම දිගටම පැවතුනද අවසාන වාරණය ක්‍රියාත්මක නොවනු ඇත.


10

පිළිතුර සරලයි ඔව් .

ආදානය:

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

නිමැවුම්:

catch
finally

1
පිළිතුර සරල නැත.
ක්‍රිස්ටෝෆ් රූසි

1
H ක්‍රිස්ටෝෆෙරූසි කෙසේද? කරුණාකර ඔබට පැහැදිලි කළ හැකිද?
හමුවන්න

1
පිළිගත් පිළිතුර කියවන්න, මුල් ප්‍රශ්නය වන්නේ 'එය සැමවිටම ක්‍රියාත්මක වේද' යන්නයි. එය සැමවිටම සිදු නොවේ. ඔබේ නඩුවේ එය එසේ වනු ඇති නමුත් මෙය මුල් ප්‍රශ්නයට පිළිතුරු නොදෙන අතර ආරම්භකයින් නොමඟ යවන සුළු විය හැකිය.
ක්‍රිස්ටෝෆ් රූසි

එවිට එය ක්‍රියාත්මක නොවන්නේ කුමන අවස්ථාවේදීද?
හමුවන්න

වෙනත් පිළිතුරු වල සඳහන් සෑම අවස්ථාවකම, පිළිගත් පිළිතුර 1000+ උඩුකුරු සමඟ බලන්න.
ක්‍රිස්ටෝෆ් රූසි

9

ඔව් එය කැඳවනු ඇත. අවසාන වශයෙන් මූලික පදයක් තිබීමේ සම්පූර්ණ කාරණය එයයි. උත්සාහක / අල්ලා ගැනීමේ වාරණයෙන් පැනීම අවසාන වාරණය මඟ හැරිය හැකි නම් එය උත්සාහය / ඇල්ලීමට පිටතින් System.out.println තැබීම හා සමාන වේ.


9

ඔව්, අවසාන වශයෙන් අවහිර කිරීම සැමවිටම ක්‍රියාත්මක වේ. බොහෝ සංවර්ධකයින් මෙම අවහිරය භාවිතා කරන්නේ දත්ත සමුදා සම්බන්ධතාවය, ප්‍රති set ල වස්තුව, ප්‍රකාශන වස්තුව වසා දැමීම සහ ගනුදෙනුව ආපසු හැරවීම සඳහා ජාවා ශිශිරතාරකයටය.


9

සැමවිටම නොවේ

ජාවා භාෂා පිරිවිතරයෙන් 14.20.2try- catch- finallyසහ try- catchබ්ලොක් ක්‍රියා කරන ආකාරය විස්තර කෙරේ . කිසිම තැනක එය වාරණය සැමවිටම ක්‍රියාත්මක වන බව සඳහන් නොකරයි . නමුත් - - සහ - බ්ලොක් සම්පූර්ණ වූ සෑම අවස්ථාවකම එය නියම කරන්නේ සම්පූර්ණ කිරීමට පෙර ක්‍රියාත්මක කළ යුතු බවයි.
finallytrycatchfinallytryfinallyfinally

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

CODE වලින් පසුව FIN ක්‍රියාත්මක වන බවට JLS සහතික නොවේ . නම් කරන JLS සහතික CODE හා ඊළගට ක්රියාත්මක වන පසුව FIN සෑම විටම පසුව ක්රියාත්මක කරනු ලැබේ CODE පෙර NEXT බවයි.

finallyබ්ලොක් එකෙන් පසුව සෑම විටම ක්‍රියාත්මක වන බවට ජේඑල්එස් සහතික නොවන්නේ ඇයි try? එය කළ නොහැකි නිසා. tryඅවහිරය සම්පූර්ණ කිරීමෙන් පසුව නමුත් වාරණය ක්‍රියාත්මක කිරීමට පෙර ජේවීඑම් ගබ්සා කිරීම (මරා දැමීම, බිඳ වැටීම, විදුලිය විසන්ධි කිරීම) සිදුවිය නොහැක්කකි finally. මෙය වළක්වා ගැනීම සඳහා ජේඑල්එස් වෙත කළ හැකි කිසිවක් නැත.

මේ අනුව, ඕනෑම මෘදුකාංගයක් ඔවුන්ගේ නිසි හැසිරීම සඳහා රඳා පවතින්නේ finallyඒවායේ tryකොටස් සම්පූර්ණ වූ පසු සෑම විටම ක්‍රියාත්මක වන කොටස් මත ය .

returntryබ්ලොක් හි ඇති උපදෙස් මෙම ගැටලුවට අදාළ නොවේ. try- catch- න් පසු ක්‍රියාත්මක කිරීම කේතය කරා ළඟා වුවහොත් , බ්ලොක් තුළ ඇති උපදෙස් සහිතව හෝ රහිතව වාරණය ක්‍රියාත්මක කිරීමට පෙර finallyසහතික වේ.finallyreturntry


8

ඔව්, එය එසේ වනු ඇත. System.exit () අමතා හෝ JVM බිඳ වැටුණොත් මිස ඔබගේ උත්සාහය හෝ අල්ලා ගැනීමේ කොටසෙහි කුමක් සිදුවේද යන්න ගැටළුවක් නොවේ. වාරණ (ය) තුළ කිසියම් ප්‍රතිලාභ ප්‍රකාශයක් තිබේ නම්, එම ආපසු ප්‍රකාශයට පෙර අවසානයේ ක්‍රියාත්මක වේ.


8

ඔව් එය එසේ වනු ඇත. ජේවීඑම් පිටවීම හෝ බිඳ වැටීම එසේ නොවේ


8

වෙනත් පිළිතුරක් නොමැති පරිදි @ විභාෂ්ගේ පිළිතුරට එකතු කිරීමෙන් පහත දැක්වෙන ආකාරයට විකෘති වස්තුවක සිදුවන්නේ කුමක්ද යන්න පැහැදිලි නොකරයි.

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

ප්‍රතිදානය කරයි

sbupdated 

ජාවා 1.8.162 අනුව, මෙය ප්‍රතිදානය නොවේ.
සෑම්

8

මම මෙය උත්සාහ කළෙමි, එය තනි නූල් ය.

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

මෙම main Threadමත වනු ඇත waitරාජ්ය සදහටම, ඒ නිසා finallyනම් කිසිදා ,

එබැවින් කොන්සෝල ප්‍රතිදානය සිදු නොවේ print String: පසු wait()හෝfinally

St ස්ටෙෆන් සී සමඟ එකඟ වූ ඉහත උදාහරණය මෙහි සඳහන් 3 වන අවස්ථාවකි :

පහත දැක්වෙන කේතයේ තවත් එවැනි අනන්ත ලූප හැකියාවන් එකතු කිරීම:

// import java.util.concurrent.Semaphore;

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 ignored) {
    } finally {
        System.out.println("finally");
    }
}

2 වන අවස්ථාව: ජේවීඑම් පළමුව බිඳ වැටේ නම්

import sun.misc.Unsafe;
import java.lang.reflect.Field;

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: ඔබ JVM එකක් බිඳ දමන්නේ කෙසේද?

6 වන අවස්ථාව: finallyඩීමන් මගින් බ්ලොක් ක්‍රියාත්මක කිරීමට යන්නේ නම් Threadසහ Threadsඊට පෙර ඩීමන් නොවන සියලුම පිටවීම් finallyකැඳවනු ලැබේ.

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

ප්‍රතිදානය: මෙය “අවසාන වශයෙන්” මුද්‍රණය නොකෙරේ, එයින් කියවෙන්නේ “ඩීමන් නූල්” හි “අවසාන වශයෙන් අවහිර කිරීම” ක්‍රියාත්මක නොවූ බවයි

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

4
පිළිගත් පිළිතුර බලන්න. මෙය "අනන්ත පුඩුවේ" අද්දර නඩුවකි.
ස්ටීවන් සී

8

පහත වැඩසටහන සලකා බලන්න:

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

ජාවා 1.8.162 අනුව, ඉහත කේත කොටස පහත ප්‍රතිදානය ලබා දෙයි:

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

මෙයින් අදහස් කරන්නේ finallyවස්තු නිදහස් කිරීම සඳහා භාවිතා කිරීම පහත කේතය වැනි හොඳ පුරුද්දක් බවයි:

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

එය sb.setLength(0)අවසානයේ තිබිය යුතු නොවේද ?
user7294900

sb.setLength (0) විසින් StringBuffer හි දත්ත හිස් කරනු ඇත. එබැවින්, sb = null වස්තුව යොමු කිරීමෙන් වෙන් කරයි.
සෑම්

නිමැවුමේ "xyz" දෙවරක් මුද්‍රණය කළ යුතු නොවේද? ශ්‍රිතය දෙවරක් කැඳවූ බැවින්, “අවසාන වශයෙන්” එක් වරක් පමණක් වූයේ ඇයි?
fresko

2
මෙය හොඳ පුරුද්දක් නොවේ. sb = null;අනවශ්‍ය කේතයක් එක් කිරීමෙන් එය අවසානයේදී අවහිර වේ. finallyදත්ත සමුදා සම්බන්ධතාවයක් හෝ ඒ හා සමාන දෙයක් නිදහස් කිරීමට හොඳ ස්ථානයක් බ්ලොක් එකක් බව මම තේරුම් ගතිමි , නමුත් ඔබේ ආදර්ශය නවකයින් ව්‍යාකූල කළ හැකි බව මතක තබා ගන්න.
රොක් බොරොනාට්

1
Am සමීම් ස්තූතියි, මම රේඛා එකතු කළ System.out.println("---AGAIN2---"); System.out.println(sb);අතර එය දැන් වඩාත් පැහැදිලි ය. ප්‍රතිදානය ඔබගේ නිබන්ධනයට විරුද්ධ විය: p මම ඔබේ පිළිතුරට ද එකතු කළෙමි, නමුත් සංස්කරණය උපපරිපාලක වරයෙකු හෝ එවැනි අයෙකු විසින් පිළිගත යුතුය. නැතිනම් ඔබට ඒවා එකතු කළ හැකිය
fresko

7

එය ඕනෑම භාෂාවක ඇත්ත වශයෙන්ම සත්‍යයකි ... අවසාන වරට සෑම විටම ආපසු ප්‍රකාශයකට පෙර ක්‍රියාත්මක වනු ඇත. එය එසේ නොවේ නම්, අවසාන වාරණයට එතරම් අර්ථයක් නැත.


7

උත්සාහක කොටසෙහි නැවත ප්‍රතිස්ථාපනය කිරීම සඳහා නැවත පැමිණීම පිළිබඳ කාරණයට අමතරව, ව්‍යතිරේකයක් සම්බන්ධයෙන් ද එය සත්‍ය වේ. ව්‍යතිරේකයක් විසි කරන අවසාන වාරණයක් උත්සාහක වාරණය තුළ සිට විසි කිරීමක් හෝ ව්‍යතිරේකයක් ප්‍රතිස්ථාපනය කරයි.


7

finally එය ක්‍රියාත්මක වන අතර එය ස්ථිරයි.

finally පහත අවස්ථා වලදී ක්‍රියාත්මක නොවේ:

නඩුව 1:

ඔබ ක්‍රියාත්මක කරන විට System.exit() .

නඩුව 2:

ඔබේ JVM / Thread බිඳ වැටෙන විට.

නඩුව 3:

ඔබගේ ක්‍රියාත්මක කිරීම අතින් අතර නතර වූ විට.


6
  1. අවසාන වශයෙන් බ්ලොක් සෑම විටම ක්රියාත්මක වේ. System.exit () ප්‍රකාශය එහි නොමැති නම් සහ (පළමු ප්‍රකාශය අවසාන වශයෙන් අවහිර කරයි).
  2. නම් system.exit () අවසානයේදී වාරණ ක්රියාත්මක වෙන්නේ නැහැ සහ පාලනය අවසානයේ වාරණ පිටතට පැමිණ පළමු ප්රකාශය වේ. System.exit () ප්‍රකාශය අවසාන වශයෙන් අවහිර වන තෙක් එම ප්‍රකාශය අවසානයේ ක්‍රියාත්මක වීම අවහිර වන අතර System.exit () දර්ශනය වූ විට පාලක බලය අවසාන වාරණයෙන් පිටතට පැමිණේ.

2
මෙයට බොහෝ වාර ගණනක් පිළිතුරු ලබා දී ඇත, එබැවින් ඔබේ පිළිතුර එකතු කරන්නේ කුමන නව තොරතුරු ද?
ටොම්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.