जावा अपवाद नहीं पकड़ा गया?


170

मुझे कोशिश-पकड़ने के निर्माण के साथ एक छोटी सैद्धांतिक समस्या है।

मैंने कल जावा के बारे में एक व्यावहारिक परीक्षा दी और मुझे निम्नलिखित उदाहरण समझ में नहीं आए:

try {
    try {
        System.out.print("A");
        throw new Exception("1");
    } catch (Exception e) {
        System.out.print("B");
        throw new Exception("2");
    } finally {
        System.out.print("C");
        throw new Exception("3");
    }
} catch (Exception e) {
    System.out.print(e.getMessage());
}

सवाल था "आउटपुट कैसा दिखेगा?"

मुझे पूरा यकीन था कि यह AB2C3, BUT सुपरराइज का सीन होगा, यह सच नहीं है।

सही उत्तर ABC3 है (परीक्षण किया गया है और वास्तव में यह ऐसा है)।

मेरा सवाल है, अपवाद ("2") कहां गया?


8
+1 आह, मैं यह जवाब जानता था। एक साक्षात्कार में मुझसे यह पूछा गया था। यह समझने का एक बहुत अच्छा सवाल है कि स्टैक पर कैसे काम करता है / पकड़ / अंत में काम करता है।
लेकिन मैं

10
केवल एक प्रिंट स्टेटमेंट है जो एक नंबर (अंतिम:) प्रिंट कर सकता है print(e.getMessage())। आपने सोचा था कि आउटपुट होगा AB2C3: क्या आपको लगता है कि सबसे बाहरी catchब्लॉक को दो बार निष्पादित किया जाएगा?
एड्रियन प्रैंक

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

जवाबों:


198

से जावा भाषा विशिष्टता 14.20.2। :

यदि कारण ब्लॉक R के लिए अचानक पूरा हो जाता है, तो अंत में ब्लॉक निष्पादित किया जाता है। फिर एक विकल्प है:

  • यदि अंत में ब्लॉक सामान्य रूप से पूरा होता है, तो प्रयास विवरण आर के लिए अचानक पूरा होता है।

  • यदि अंत में कारण एस के लिए अचानक पूरा हो जाता है, तो कोशिश बयान एस (और कारण आर को त्याग दिया जाता है) के लिए अचानक पूरा करता है

इसलिए, जब कोई अपवाद होता है जो एक कैच ब्लॉक होता है:

try {
    // ...
} catch (Exception e) {
    throw new Exception("2");
}

लेकिन अंत में एक ब्लॉक भी है जो एक अपवाद भी फेंकता है:

} finally {
    throw new Exception("3");
}

Exception("2")छोड़ दिया जाएगा और केवल Exception("3")प्रचार किया जाएगा।


72
यह returnकथन के लिए भी सही है । यदि आपके अंत में ब्लॉक की वापसी है, तो यह किसी भी ब्लॉक tryया catchब्लॉक में किसी भी रिटर्न को ओवरराइड करेगा । इन "सुविधाओं" के कारण, एक अच्छा अभ्यास यह है कि अंत में ब्लॉक को कभी भी अपवाद नहीं फेंकना चाहिए या रिटर्न स्टेटमेंट नहीं देना चाहिए ।
अगस्तो

यह भी जावा में 7. इनहेरिट बेनिफिट ट्राय-विथ-रिसोर्सेस है। यह प्रारंभिक अपवाद को संरक्षित करता है यदि संसाधनों को बंद करते समय द्वितीयक अपवाद उत्पन्न होता है, आमतौर पर डिबगिंग को आसान बनाते हैं।
w25r

19

अंत में ब्लॉक में फेंके गए अपवाद पहले से आजमाए गए या पकड़ने वाले ब्लॉक में दिए गए अपवाद को दबा देते हैं।

जावा 7 उदाहरण: http://ideone.com/0YdeZo

से जावाडोक के उदाहरण:


static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

हालाँकि, इस उदाहरण में, यदि विधियाँ पढ़ती हैं और दोनों थ्रो अपवादों को बंद कर देती हैं, तो विधि पठनFirstLineFromFileWithFinallyBlock अंत में ब्लॉक से फेंके गए अपवाद को फेंक देती है; कोशिश ब्लॉक से फेंके गए अपवाद को दबा दिया गया है।


try-withजावा 7 का नया सिंटैक्स अपवाद दमन का एक और चरण जोड़ता है: कोशिश ब्लॉक में फेंके गए अपवाद पहले-कोशिश किए गए भाग में फेंक दिए गए लोगों को दबा देते हैं।

उसी उदाहरण से:

try (
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }

एक अपवाद कोशिश-कोड संसाधनों के साथ जुड़े कोड के ब्लॉक से फेंका जा सकता है। उपरोक्त उदाहरण में, ट्रायल ब्लॉक से एक अपवाद को फेंका जा सकता है, और दो अपवादों को ट्राइ-रिसोर्स संसाधनों के स्टेटमेंट से फेंका जा सकता है, जब यह जिपफाइल और बफर्डविटर ऑब्जेक्ट्स को बंद करने की कोशिश करता है। यदि प्रयास ब्लॉक से एक अपवाद को फेंक दिया जाता है और एक या अधिक अपवादों को प्रयास-के-संसाधन विवरण से फेंक दिया जाता है, तो उन अपवादों को प्रयास-से-संसाधनों के कथन से दबा दिया जाता है, और ब्लॉक द्वारा फेंका गया अपवाद एक है यह लिखने के द्वारा फेंक दिया जाता है ।TileFileZipFileContents विधि। आप इन ब्लॉक किए गए अपवादों को पुनः प्रयास ब्लॉक द्वारा फेंके गए अपवाद से Throwable.getSuppressed पद्धति से कॉल करके प्राप्त कर सकते हैं।


प्रश्न से कोड में, प्रत्येक ब्लॉक स्पष्ट रूप से पुराने अपवाद को छोड़ रहा है, इसे लॉग भी नहीं कर रहा है, अच्छा नहीं है जब आप कुछ प्रश्नों को हल करने की कोशिश कर रहे हैं:

http://en.wikipedia.org/wiki/Error_hiding


9

चूंकि ब्लॉक throw new Exception("2");से फेंका गया catchहै और नहीं try, यह फिर से पकड़ा नहीं जाएगा। 14.20.2
देखें । प्रयत्न-अंत में प्रयास और अंत में पकड़ने की कोशिश

यह क्या हो रहा है:

try {
    try {
        System.out.print("A");         //Prints A
        throw new Exception("1");   
    } catch (Exception e) { 
        System.out.print("B");         //Caught from inner try, prints B
        throw new Exception("2");   
    } finally {
        System.out.print("C");         //Prints C (finally is always executed)
        throw new Exception("3");  
    }
} catch (Exception e) {
    System.out.print(e.getMessage());  //Prints 3 since see (very detailed) link
}

हां यह सही है, मैं देख रहा हूं कि यह हो रहा है, लेकिन मैं स्पष्टीकरण की तलाश कर रहा था - यह इस तरह से व्यवहार क्यों कर रहा है
कौसलिक

5

आपका प्रश्न बहुत स्पष्ट है, और इसका उत्तर उसी सीमा तक सरल है .. संदेश के साथ अपवाद वस्तु "2" को संदेश के साथ अपवाद वस्तु द्वारा "3" के रूप में अधिलेखित किया गया है।

स्पष्टीकरण: जब कोई अपवाद होता है, तो उसकी वस्तु को संभालने के लिए ब्लॉक को पकड़ने के लिए फेंक दिया जाता है। लेकिन जब अपवाद कैच ब्लॉक में होता है, तो इसका ऑब्जेक्ट अपवाद हैंडलिंग के लिए OUTER CATCH ब्लॉक (यदि कोई हो) में स्थानांतरित हो जाता है। और वही हुआ। संदेश "2" के साथ अपवाद ऑब्जेक्ट OUTER कैच ब्लॉक में स्थानांतरित हो जाता है। लेकिन रुकिए .. इनर-ट्राई-कैच ब्लॉक को छोड़ने से पहले इसे अंतिम रूप से देखें। यहां वह परिवर्तन हुआ जिसके बारे में हम चिंतित हैं। एक नया EXCEPTION ऑब्जेक्ट (संदेश "3" के साथ) बाहर फेंक दिया गया है या यह अंत में ब्लॉक किया गया है जिसने पहले से ही फेंक दिया अपवाद वस्तु (संदेश "2" के साथ) को प्रतिस्थापित किया है। जिसके परिणामस्वरूप, जब अपवाद वस्तु का संदेश मुद्रित होता है, तो हमें मिला। ओवरराइड वैल्यू यानी "3" और "2" नहीं।

याद रखें: केवल एक अपवाद वस्तु को CATCH ब्लॉक पर नियंत्रित किया जा सकता है।


2

finallyब्लॉक हमेशा चलाता है। या तो आप returnकोशिश ब्लॉक के अंदर से या एक अपवाद फेंक दिया गया है। finallyब्लॉक में फेंका गया अपवाद कैच ब्रांच में फेंके गए एक को ओवरराइड करेगा।

इसके अतिरिक्त, एक अपवाद को फेंकने से कोई भी आउटपुट स्वयं उत्पन्न नहीं होगा। रेखा throw new Exception("2");बाहर कुछ नहीं लिखेगी।


1
हाँ, मुझे पता है कि अपवाद उत्पादन खुद से कुछ भी नहीं फेंक रहा है, लेकिन मैंने कारण नहीं देखा, अपवाद 2 को छोड़ दिया जाना चाहिए। मैं फिर से थोड़ा चालाक हूँ :-)
कौसलिक

हमेशा बहुत लंबा समय होता है और बहुत लंबे समय में कुछ भी हो सकता है (पहेली wouter.coekaerts.be/2012/puzzle-dreams देखें )
Dainius

0

आपके कोड के अनुसार:

try {
    try {
        System.out.print("A");
        throw new Exception("1");   // 1
    } catch (Exception e) {
        System.out.print("B");      // 2
        throw new Exception("2");
    } finally {                     // 3
        System.out.print("C");      // 4 
        throw new Exception("3");
    }
} catch (Exception e) {             // 5
    System.out.print(e.getMessage());
}

जैसा कि आप यहां देख सकते हैं:

  1. प्रिंट ए और थ्रो अपवाद # 1;
  2. यह अपवाद कैच स्टेटमेंट और प्रिंट द्वारा पकड़ा गया है B - # 2;
  3. ब्लॉक अंत में # 3ट्राइ-कैच के बाद निष्पादित होता है (या केवल प्रयास करें, यदि कोई अपवाद नहीं हुआ है) कथन और प्रिंट C - # 4और नए अपवाद को फेंक दिया;
  4. यह एक बाहरी कैच स्टेटमेंट द्वारा पकड़ा गया है # 5;

परिणाम है ABC3। और 2उसी तरह से छोड़ा गया है1


क्षमा करें, अपवाद ("1") छोड़ा नहीं गया है, लेकिन सफलतापूर्वक पकड़ा गया है
Black Maggie

@ ब्लेक मैगी यह कैश्ड है और नए अपवाद को फेंक दिया गया है => यह कैश्ड नहीं है और प्रोग्राम समाप्त हो गया है। और इससे पहले कि ब्लॉक अंत में निष्पादित होता है।
nazar_art
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.