java आखिरकार जावा में हमेशा अवरुद्ध हो जाता है?




return try-catch-finally (24)

इस कोड को ध्यान में रखते हुए, क्या मैं पूरी तरह से सुनिश्चित हो सकता हूं कि 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.");
}

मैंने उपरोक्त उदाहरण को मामूली संशोधन के साथ करने की कोशिश की-

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 को आवंटित किया जाता है और फिर System.out आउट निष्पादित किया जाता है।

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

यदि आप ग्रहण में इस कोड को डीबग करेंगे तो आपको एक एहसास होगा कि finally System.out ब्लॉक को निष्पादित करने के बाद try ब्लॉक के return स्टेटमेंट को फिर से निष्पादित किया जाता है। पर ये स्थिति नहीं है। यह बस मूल्य 2 देता है।


उदाहरण कोड:

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

अगर एक अपवाद फेंक दिया जाता है, तो अंत में चलता है। यदि कोई अपवाद नहीं फेंक दिया जाता है, तो आखिरकार चलता है। अगर अपवाद पकड़ा जाता है, तो अंत में चलता है। अगर अपवाद पकड़ा नहीं जाता है, तो अंत में चलता है।

जेवीएम बाहर निकलने पर केवल समय नहीं चलता है।


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

14.20.2। आखिरकार कोशिश करें और आखिरकार कोशिश करें

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

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

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

जेएलएस 14.17 रिटर्न स्टेटमेंट

ReturnStatement:
     return Expression(opt) ;

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

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

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


हाँ यह होगा। केवल मामला यह जेवीएम बाहर निकलना या दुर्घटनाग्रस्त नहीं होगा


आखिरकार ब्लॉक का यही विचार है। यह आपको यह सुनिश्चित करने देता है कि आप क्लीनअप करते हैं जो अन्यथा छोड़े जा सकते हैं क्योंकि आप अन्य चीज़ों के साथ वापस आते हैं।

अंत में प्रयास ब्लॉक में क्या होता है इस पर ध्यान दिए बिना ( जब तक आप System.exit(int) या जावा वर्चुअल मशीन को किसी अन्य कारण से बाहर नहीं निकालते)।


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


संक्षेप में, आधिकारिक जावा दस्तावेज़ीकरण ( here क्लिक here ) में, यह लिखा गया है कि -

यदि कोशिश या पकड़ कोड निष्पादित किया जा रहा है, तो JVM बाहर निकलता है, तो आखिरकार ब्लॉक निष्पादित नहीं हो सकता है। इसी प्रकार, यदि कोशिश या पकड़ कोड निष्पादित करने वाला थ्रेड बाधित या मारे गए हैं, तो आखिर में ब्लॉक जारी नहीं हो सकता है, भले ही एप्लिकेशन पूरी तरह से जारी रहे।


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


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


जवाब सरल है हाँ

इनपुट:

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

इसके अलावा, हालांकि यह खराब अभ्यास है, अगर अंत में ब्लॉक के भीतर रिटर्न स्टेटमेंट है, तो यह नियमित ब्लॉक से किसी भी अन्य रिटर्न को ट्रम्प करेगा। यही है, निम्नलिखित ब्लॉक झूठी वापसी करेगा:

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

आखिरकार ब्लॉक से अपवाद फेंकने के साथ वही बात।


आखिरकार हमेशा चल रहा है कि यह पूरा बिंदु है, सिर्फ इसलिए कि रिटर्न के बाद कोड में दिखाई देता है इसका मतलब यह नहीं है कि यह कैसे लागू किया गया है। try ब्लॉक से बाहर निकलने पर जावा रनटाइम को इस कोड को चलाने की ज़िम्मेदारी है।

उदाहरण के लिए यदि आपके पास निम्नलिखित हैं:

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

रनटाइम इस तरह कुछ उत्पन्न करेगा:

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

यदि एक अनिश्चित अपवाद फेंक दिया जाता है तो finally ब्लॉक चल जाएगा और अपवाद प्रचार जारी रहेगा।


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



इसके बारे में सोचने का एक तार्किक तरीका है:

  1. आखिरकार ब्लॉक में रखा गया कोड निष्पादित किया जाना चाहिए जो कोशिश ब्लॉक के भीतर होता है
  2. तो यदि कोशिश ब्लॉक में कोड किसी मान को वापस करने या अपवाद फेंकने का प्रयास करता है तो आइटम को 'शेल्फ पर' रखा जाता है जब तक अंत में ब्लॉक निष्पादित नहीं हो जाता
  3. चूंकि अंत में ब्लॉक में कोड (परिभाषा के अनुसार) एक उच्च प्राथमिकता है, जो इसे पसंद या वापस फेंक सकता है। किस मामले में 'शेल्फ पर' छोड़ा गया कुछ भी त्याग दिया जाता है।
  4. इसका एकमात्र अपवाद यह है कि यदि वीएम प्रयास प्रणाली के दौरान पूरी तरह से बंद हो जाता है जैसे 'System.exit'

क्योंकि फाइनल हमेशा आपके पास जो भी मामलों में बुलाया जाता है। आपके पास अपवाद नहीं है, इसे अभी भी कहा जाता है, अपवाद पकड़ो, इसे अभी भी बुलाया जाता है


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

निम्नलिखित कार्यक्रम पर विचार करें:

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

जावा 1.8.162 के अनुसार, उपरोक्त कोड ब्लॉक निम्न आउटपुट देता है:

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

इसका मतलब यह है कि finally वस्तुओं को मुक्त करने के लिए निम्नलिखित कोड की तरह एक अच्छा अभ्यास है:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null;
    }
}

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

finally केवल एक बार नहीं कहा जाएगा:

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

क्योंकि जब तक आप System.exit() (या थ्रेड क्रैश) को कॉल नहीं करते हैं, तब तक अंततः ब्लॉक को तब तक बुलाया जाएगा।


आखिरकार ब्लॉक हमेशा तब तक निष्पादित होता है जब तक कि असामान्य प्रोग्राम समाप्ति न हो, या तो JVM क्रैश या कॉल से System.exit(0) परिणामस्वरूप।

इसके शीर्ष पर, अंत में ब्लॉक के भीतर से लौटाया गया कोई भी मूल्य आखिरकार ब्लॉक के निष्पादन से पहले लौटाए गए मान को ओवरराइड करेगा, इसलिए अंततः प्रयास करने के दौरान सभी निकास बिंदुओं की जांच करने से सावधान रहें।


इस कोड को आज़माएं, आप समझेंगे कि अंत में ब्लॉक को रिटर्न स्टेटमेंट के बाद निष्पादित किया जाएगा

public class TestTryCatchFinally {
    static int x = 0;

    public static void main(String[] args){
        System.out.println(f1() );
        System.out.println(f2() );
    }

    public static int f1(){
        try{
            x = 1;
            return x;
        }finally{
            x = 2;
        }
    }

    public static int f2(){
        return x;
    }
}

अंत में हमेशा निष्पादित करें कि क्या अपवाद हैंडल है या नहीं। अगर किसी भी अपवाद को ब्लॉक करने से पहले अपवाद हुआ तो आखिरकार ब्लॉक निष्पादित नहीं होगा।







try-catch-finally