क्या जावा में अंतिम ब्लॉक हमेशा निष्पादित होता है?


2382

इस कोड को ध्यान में रखते हुए, क्या मुझे पूरा यकीन है कि finallyब्लॉक हमेशा निष्पादित होता है, कोई फर्क नहीं पड़ता कि क्या something()है?

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

471
यदि ऐसा नहीं होता है, तो probablyइसके बजाय कीवर्ड का नाम होना चाहिए ।
दोपहर रेशम



2
प्रभावी जावा का कहना है अन्यथा informit.com/articles/article.aspx?p=1216151&seqNum=7
बिनॉय बाबू

27
@BinoyBabu, finalizer =! finally; अंतिम रूप == finalize()विधि।
jaco0646

जवाबों:


2697

हां, या कोड ब्लॉक finallyके निष्पादन के बाद बुलाया जाएगा ।trycatch

केवल समय finallyको नहीं बुलाया जाएगा:

  1. अगर तुम आह्वान करते हो System.exit()
  2. अगर तुम आह्वान करते हो Runtime.getRuntime().halt(exitStatus)
  3. अगर JVM पहले क्रैश हो जाता है
  4. यदि JVM एक अनंत लूप (या कुछ अन्य गैर-रुकावट, गैर-समाप्ति बयान) tryया catchब्लॉक में पहुंचता है
  5. यदि ओएस जबरन JVM प्रक्रिया को समाप्त करता है; जैसे, kill -9 <pid>UNIX पर
  6. यदि मेजबान प्रणाली मर जाती है; उदाहरण के लिए, बिजली की विफलता, हार्डवेयर त्रुटि, ओएस घबराहट, एट वगैरह
  7. यदि finallyब्लॉक को एक डेमन थ्रेड द्वारा निष्पादित किया जा रहा है और अन्य सभी गैर-डेमन थ्रेड्स को बाहर निकलने से पहले finallyबुलाया जाता है

44
वास्तव में thread.stop()जरूरी नहीं कि finallyब्लॉक को क्रियान्वित होने से रोका जाए ।
पिओटर फाइंडसेन

181
कैसे के बारे में हम कहते हैं कि finallyब्लॉक बुलाया जाएगा के बादtry ब्लॉक, और इससे पहले कि नियंत्रण निम्नलिखित बयानों के लिए गुजरता है। यह एक अनंत लूप को शामिल करने वाले ब्लॉक के अनुरूप है और इसलिए अंत में ब्लॉक वास्तव में कभी नहीं लगाया जा रहा है।
आंद्रेज डोयले

9
एक और मामला भी है, जब हम नेस्टेड -कैच-अंततः- ब्लॉक का उपयोग करते हैं
ruhungry

7
अंत में, डेमॉन थ्रेड द्वारा फेंके गए अपवाद के मामले में ब्लॉक को नहीं कहा जाता है।
अमरीश पांडे

14
@BinoyBabu - यह फाइनल के बारे में है, अंत में ब्लॉक नहीं
avmohan

567

उदाहरण कोड:

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 करें: C # में व्यवहार इस तथ्य से अलग है कि स्टेटमेंट को इन- finallyक्लॉज के साथ बदलने की return 2;अनुमति नहीं है (कंपाइलर-एरर)।
अलेक्जेंडर पाचा

15
यहाँ एक महत्वपूर्ण विवरण से अवगत होना है: stackoverflow.com/a/20363941/2684342
वुडन किटी

18
तुम भी अंत में अपने आप में एक वापसी बयान जोड़ सकते हैं, जो फिर पिछले वापसी मूल्य को ओवरराइड करेगा। यह भी जादुई अपवादों को छोड़ देता है। उस बिंदु पर, आपको अपने कोड को फिर से भरने पर विचार करना चाहिए।
Zyl

8
यह वास्तव में साबित नहीं होता है कि आखिरकार ट्रम्प वापसी करते हैं। रिटर्न मान कॉलर कोड से मुद्रित किया जाता है। ज्यादा साबित नहीं होता है।
त्रिमटब

20
क्षमा करें, लेकिन यह एक प्रमाण है प्रदर्शन नहीं। यह केवल एक प्रमाण है यदि आप यह दिखा सकते हैं कि यह उदाहरण हमेशा सभी जावा प्लेटफार्मों पर इस तरह से व्यवहार करता है, और इसी तरह के उदाहरण भी हमेशा इस तरह से व्यवहार करते हैं।
स्टीफन सी

391

इसके अलावा, हालांकि यह बुरा अभ्यास है, अगर अंत में ब्लॉक के भीतर रिटर्न स्टेटमेंट है, तो यह नियमित ब्लॉक से किसी अन्य रिटर्न को ट्रम्प करेगा। अर्थात्, निम्न खंड गलत वापस आ जाएगा:

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

अंत में ब्लॉक से अपवाद फेंकने के साथ एक ही बात।


95
यह वास्तव में एक बुरा अभ्यास है। इसके खराब होने के बारे में अधिक जानकारी के लिए stackoverflow.com/questions/48088/… देखें ।
जॉन मेघेर

23
माना। अंत में एक वापसी {} कोशिश {} में फेंके गए किसी अपवाद को अनदेखा करता है। भयानक!
neu242

8
@ dominicbri7 आपको क्यों लगता है कि यह एक बेहतर अभ्यास है? और फ़ंक्शन / विधि शून्य होने पर इसे अलग क्यों होना चाहिए?
corsiKa

8
उसी कारण से मैं अपने C ++ कोड में गोटो का उपयोग नहीं करता। मुझे लगता है कि कई रिटर्न पढ़ना मुश्किल है और डीबग करना अधिक कठिन है (वास्तव में सरल मामलों में यह लागू नहीं होता है)। मुझे लगता है कि यह केवल व्यक्ति की पसंद है और अंत में आप या तो विधि का उपयोग करके एक ही चीज़ प्राप्त कर सकते हैं
अधिवास

16
जब किसी प्रकार का असाधारण मामला होता है तो मैं कई रिटर्न का उपयोग करता हूं। जैसे अगर (जारी न रखने का एक कारण है) वापसी;
२३:२३ बजे २३:१३

257

यहाँ जावा भाषा विशिष्टता से आधिकारिक शब्द हैं।

14.20.2। कोशिश और अंत में पकड़ने की कोशिश-अंत में निष्पादन

पहले ब्लॉक को निष्पादित करके ब्लॉक के tryसाथ एक स्टेटमेंट finallyनिष्पादित किया जाता है try। फिर एक विकल्प है:

  • यदि tryब्लॉक का निष्पादन सामान्य रूप से पूरा होता है, तो [...]
  • के निष्पादन तो tryब्लॉक क्योंकि एक के अचानक पूरा करता है throwएक मूल्य के वी , [...]
  • यदि tryब्लॉक का निष्पादन किसी अन्य कारण R के लिए अचानक पूरा हो जाता है , तो finallyब्लॉक निष्पादित किया जाता है। फिर एक विकल्प है:
    • यदि अंत में ब्लॉक सामान्य रूप से पूरा होता है, तो tryकथन आर के लिए अचानक पूरा हो जाता है ।
    • यदि finallyब्लॉक कारण S के लिए अचानक पूरा होता है , तो tryकथन S ( और कारण R को छोड़ दिया जाता है ) के कारण अचानक पूरा हो जाता है

returnवास्तव में इसके लिए विनिर्देश स्पष्ट है:

JLS 14.17 रिटर्न स्टेटमेंट

ReturnStatement:
     return Expression(opt) ;

विधि या कंस्ट्रक्टर के आक्रमणकर्ता पर नियंत्रण स्थानांतरित करने का returnकोई Expression प्रयासकरने वाला एक बयान जिसमें यह शामिल है।

उस विधि के इनकोकर पर नियंत्रण स्थानांतरित करने के प्रयासों केreturn साथ एक बयान जिसमें यह शामिल है; का मूल्य विधि मंगलाचरण का मूल्य हो जाता है।Expression Expression

पूर्ववर्ती वर्णन कहते हैं कि " प्रयास हस्तांतरण नियंत्रित करने के लिए " के बजाय सिर्फ " स्थानान्तरण को नियंत्रित " क्योंकि यदि कोई हो tryविधि या निर्माता जिसका भीतर बयान tryब्लॉक शामिल returnबयान, तो कोई भी finallyउन लोगों में से खंड tryबयान, क्रम में सबसे बाहरी को निष्पादित किया जाएगा, अंतरतम , इससे पहले कि नियंत्रण विधि या कंस्ट्रक्टर के आक्रमणकर्ता को स्थानांतरित कर दिया जाए। एक finallyखंड के अचानक पूरा होने से एक returnबयान द्वारा शुरू किए गए नियंत्रण के हस्तांतरण को बाधित किया जा सकता है ।


163

अन्य प्रतिक्रियाओं के अलावा, यह बताना महत्वपूर्ण है कि 'आखिर' के पास किसी भी अपवाद / वापसी मूल्य को ओवरराइड करने का अधिकार है। उदाहरण के लिए, निम्नलिखित कोड 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
कौन नहीं चाहता है एक अधूरा OutOfMemoryError? ;)
RecursiveExceptionException

मैंने इसका परीक्षण किया और यह इस तरह की त्रुटि (yipes!) को दबाता है। यह भी एक चेतावनी उत्पन्न करता है जब मैं इसे संकलित करता हूं (याय!)। और आप इसके चारों ओर एक रिटर्न वैरिएबल को परिभाषित करके और फिर ब्लॉक के 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 का मूल्यांकन करता है, इसीलिए मैंने इसे बदल दिया है। लौटे मूल्य को प्रभावित नहीं करता है, मुझे सही करें।
18:15 पर meexplorer

लेकिन मुझे इस बारे में कोई सबूत नहीं मिला, जहां यह उल्लेख है कि वापसी फिर से अभिव्यक्ति का मूल्यांकन नहीं करती है।
meexplorer

1
@ मीक्सप्लैपर थोड़ा देर से, लेकिन इसे JLS 14.20.2 में समझाया गया है प्रयास-अंत और कोशिश-कैच-अंततः का निष्पादन - शब्द जटिल, 14.17। रिटर्न स्टेटमेंट को भी अवश्य पढ़ें
user85421

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()यहां) अभी भी इससे पहले आती है।
अल्बर्ट

सभी 3 "रिटर्निंग" अंक के साथ एक अच्छा उदाहरण!
राडिस्टाओ

नहीं। ऊपर दिए गए कोड 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. इसका एकमात्र अपवाद यह है कि अगर वीएम 'System.exit' द्वारा कोशिश ब्लॉक के दौरान पूरी तरह से बंद हो जाता है

10
क्या यह सिर्फ "इसके बारे में सोचने का एक तार्किक तरीका है" या क्या यह वास्तव में है कि आखिर स्पेसिफिकेशंस के अनुसार काम करने का इरादा कैसे है? सन रिसोर्स का लिंक यहां बहुत दिलचस्प होगा।
मत्ती

21

अंत में हमेशा निष्पादित किया जाता है जब तक कि असामान्य प्रोग्राम समाप्ति नहीं होती है (जैसे कि System.exit (0) ..) को कॉल करना। तो, आपका sysout प्रिंट हो जाएगा



18

अंततः ब्लॉक को हमेशा निष्पादित किया जाता है जब तक कि असामान्य कार्यक्रम समाप्ति न हो, या तो जेवीएम क्रैश या कॉल से 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 () नहीं कहना चाहिए ...
Franz D.

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 कोशिश या कैच कोड निष्पादित करते समय बाहर निकलता है, तो अंत में ब्लॉक निष्पादित नहीं हो सकता है। इसी तरह, यदि कोशिश या कैच कोड को निष्पादित करने वाला थ्रेड बाधित होता है या मारा जाता है, तो अंततः ब्लॉक भले ही निष्पादित न हो, लेकिन एप्लिकेशन पूरी तरह से जारी रहता है।


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
@ChristopheRoussy कैसे? क्या आप कृपया समझा सकते हैं?
मिलें

1
स्वीकृत उत्तर को पढ़ें, मूल प्रश्न 'क्या यह हमेशा निष्पादित होता है' के बारे में है और यह हमेशा नहीं होगा। आपके मामले में यह होगा लेकिन यह मूल प्रश्न का उत्तर नहीं देता है और शुरुआती भ्रामक भी हो सकता है।
क्रिस्टोफ रूसो

तो किस मामले में इसे निष्पादित नहीं किया जाएगा?
मिलें

अन्य उत्तरों में उल्लिखित सभी मामलों में, 1000+ upvotes के साथ स्वीकृत उत्तर देखें।
क्रिस्टोफ रूसो

9

हाँ यह बुलाया जाएगा। अंत में कीवर्ड होने की पूरी बात है। यदि कोशिश / कैच ब्लॉक से बाहर कूदना बस अंततः ब्लॉक को छोड़ सकता है तो यह कोशिश / कैच के बाहर System.out.println डालने जैसा ही था।


9

हां, आखिरकार ब्लॉक हमेशा निष्पादित होता है। अधिकांश डेवलपर इस ब्लॉक का उपयोग डेटाबेस कनेक्शन, परिणाम ऑब्जेक्ट, स्टेटमेंट ऑब्जेक्ट को बंद करने के लिए करते हैं और लेनदेन को रोलबैक करने के लिए जावा हाइबरनेट में भी उपयोग करते हैं।


9

हर बार नहीं

जावा भाषा विशिष्टता वर्णन करता है कि try- catch- finallyऔर try- catchब्लॉक में काम 14.20.2
यह कोई जगह में यह बताता है कि finallyब्लॉक हमेशा मार डाला जाता है। लेकिन सभी मामलों के लिए try- जिसमें - catch- finallyऔर try- finallyब्लॉक पूरा होता है, यह निर्दिष्ट करता है कि पूरा होने से पहले finallyनिष्पादित किया जाना चाहिए।

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

JLS इस बात की गारंटी नहीं देता है कि CODE के बाद फिन को निष्पादित किया गया है । JLS गारंटी देता है कि यदि CODE और NEXT को निष्पादित किया जाता है, तो हमेशा CODE के बाद और NEXT से पहले फिन को निष्पादित किया जाएगा ।

जेएलएस इस बात की गारंटी क्यों नहीं देता कि finallyब्लॉक को हमेशा tryब्लॉक के बाद निष्पादित किया जाता है? क्योंकि यह असंभव है। यह संभव नहीं है लेकिन संभव है कि tryब्लॉक को पूरा करने के बाद जेवीएम को खत्म कर दिया जाएगा (मार, दुर्घटना, बिजली बंद) finally। इससे बचने के लिए जेएलएस कुछ भी नहीं कर सकता है।

इस प्रकार, कोई भी सॉफ्टवेयर जो उनके उचित व्यवहार के लिए finallyब्लॉकों पर निर्भर करता है हमेशा उनके tryब्लॉक पूर्ण होने के बाद निष्पादित किया जाता है।

returntryब्लॉक में निर्देश इस मुद्दे के लिए अप्रासंगिक हैं। यदि निष्पादन के बाद कोड तक पहुँच जाता है try- catch- finallyयह गारंटी दी जाती है कि finallyब्लॉक को ब्लॉक के returnअंदर या बिना निर्देशों के पहले निष्पादित किया गया होगा try


8

हाँ यह होगा। जब तक System.exit () नामक या JVM क्रैश नहीं हो जाता, तब तक कोई फर्क नहीं पड़ता कि आपकी कोशिश या ब्लॉक को पकड़ना क्या होता है। यदि ब्लॉक में कोई रिटर्न स्टेटमेंट है, तो उस रिटर्न स्टेटमेंट से पहले अंतिम रूप से निष्पादित किया जाएगा।


8

हाँ यह होगा। केवल यह मामला नहीं है जेवीएम बाहर निकलता है या क्रैश होता है


8

को जोड़ना @ vibhash के जवाब के रूप में कोई अन्य जवाब बताता है कि नीचे एक तरह एक परिवर्तनशील वस्तु के मामले में होता है।

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

@Stephen C के साथ सहमत, उपरोक्त उदाहरण यहाँ वर्णित 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);
}

रेफरी: आप एक जेवीएम को कैसे दुर्घटनाग्रस्त करते हैं?

केस 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) डेटा को स्ट्रिंगबर्गर में खाली कर देगा। इसलिए, sb = null ऑब्जेक्ट को संदर्भ से अलग कर देगा।
सैम

क्या "xyz" को आउटपुट में दो बार प्रिंट नहीं किया जाना चाहिए? चूंकि फ़ंक्शन को दो बार बुलाया गया था, इसलिए "अंततः" केवल एक बार ही क्यों था?
फ्रेस्को

2
यह एक अच्छा अभ्यास नहीं है। अंत में ब्लॉक के साथ sb = null;बस अनावश्यक कोड जोड़ता है। मैं समझता हूं कि आपका मतलब है कि एक finallyब्लॉक डेटाबेस या कनेक्शन जैसे कुछ संसाधनों को मुक्त करने के लिए एक अच्छी जगह है, लेकिन ध्यान रखें कि आपका उदाहरण नए लोगों को भ्रमित कर सकता है।
Roc Boronat

1
@ शमीम थैंक्स, मैंने लाइनें जोड़ दीं System.out.println("---AGAIN2---"); System.out.println(sb);और यह अब और स्पष्ट है। जैसा कि यह था, आउटपुट आपके थीसिस के खिलाफ था: पी मैंने भी आपके उत्तर में जोड़ा है, लेकिन संपादन को एक मध्यस्थ या किसी अन्य व्यक्ति द्वारा स्वीकार किया जाना चाहिए। वरना आप उन्हें जोड़ सकते हैं
fresko

7

यह वास्तव में किसी भी भाषा में सच है ... अंत में हमेशा रिटर्न स्टेटमेंट से पहले निष्पादित होगा, कोई फर्क नहीं पड़ता कि जहां वापसी विधि बॉडी में है। यदि ऐसा नहीं होता, तो अंत में ब्लॉक का बहुत अर्थ नहीं होता।


7

अंत में वापसी के बारे में बिंदु के अलावा कोशिश ब्लॉक में वापसी की जगह है, वही अपवाद का सच है। अंत में एक अपवाद को फेंकने वाला ब्लॉक कोशिश ब्लॉक के भीतर से लौटाए गए अपवाद या अपवाद को बदल देगा।


7

finally निष्पादित करेगा और यह सुनिश्चित करने के लिए है।

finally नीचे के मामलों में निष्पादित नहीं होगा:

मामला एक :

जब आप निष्पादित कर रहे हैं System.exit()

मामला 2:

जब आपका JVM / थ्रेड क्रैश हो जाता है।

केस 3:

जब आपका निष्पादन मैन्युअल रूप से बीच में रोक दिया जाता है।


6
  1. अंत में ब्लॉक हमेशा निष्पादित होता है। जब तक और System.exit () स्टेटमेंट वहां मौजूद नहीं होता (अंत में ब्लॉक में पहला स्टेटमेंट)।
  2. यदि system.exit () पहला स्टेटमेंट है, तो अंत में ब्लॉक निष्पादित नहीं होगा और नियंत्रण अंततः ब्लॉक से बाहर आ जाएगा। जब भी System.exit () स्टेटमेंट अंत तक ब्लॉक हो जाता है, तब तक स्टेटमेंट एक्सेप्ट ब्लॉक हो जाता है और जब System.exit () दिखाई देता है तो कंट्रोल फोर्स पूरी तरह से आखिरकार ब्लॉक से बाहर आ जाता है।

1
इसका उत्तर कई बार दिया गया है, इसलिए आपका उत्तर कौन सी नई जानकारी जोड़ता है?
टॉम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.