क्या मैं जावा 7 कोशिश-के-संसाधनों का सही तरीके से उपयोग कर रहा हूँ


87

मैं बफ़र किए गए पाठक और फ़ाइल रीडर से अपेक्षा कर रहा हूँ कि अपवाद को छोड़ दिया जाए और जारी किए गए संसाधन।

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
    try (BufferedReader br = new BufferedReader(new FileReader(filePath)))
    {
        return read(br);
    } 
}

हालांकि, catchसफल समापन के लिए एक खंड होने की आवश्यकता है?

संपादित करें:

अनिवार्य रूप से, जावा 6 के लिए नीचे दिए गए बराबर जावा 7 में उपरोक्त कोड है:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{

    BufferedReader br = null;

    try
    {
        br = new BufferedReader(new FileReader(filePath));

        return read(br);
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        try
        {
            if (br != null) br.close();
        }
        catch(Exception ex)
        {
        }
    }

    return null;
}

आपके प्रश्न को फिर से पढ़ने के बाद, मुझे यकीन नहीं है कि अगर मैं इसे अच्छी तरह से समझता हूं। क्या आप इसे समझा सकते हैं?
मारून

नमस्ते। चीता, मैं पहले की भूमिका को समझने की कोशिश कर रहा हूंcatch जावा 6 के लिए आपके उदाहरण की यानी catch (Exception ex) { throw ex; }- यह केवल अपवाद को फिर से फेंक रहा है, यह कुछ भी नहीं कर रहा है, इसे आसानी से बिना किसी चोट के हटाया जा सकता है। या क्या मैं कुछ न कुछ भूल रहा हूं?
साशा

जवाबों:


103

यह सही है और catchखंड के लिए कोई आवश्यकता नहीं है । ओरेकल जावा 7 डॉक का कहना है कि अपवाद को वास्तव में फेंक दिया गया है या नहीं, इसकी परवाह किए बिना संसाधन बंद कर दिया जाएगा ।

catchयदि आप अपवाद पर प्रतिक्रिया करना चाहते हैं तो आपको केवल एक खंड का उपयोग करना चाहिए । catchखंड निष्पादित किया जाएगा के बाद संसाधन बंद कर दिया है।

यहाँ Oracle के ट्यूटोरियल से एक स्निपेट दिया गया है :

निम्न उदाहरण एक फ़ाइल से पहली पंक्ति पढ़ता है। यह फ़ाइल से डेटा पढ़ने के लिए BufferedReader के एक उदाहरण का उपयोग करता है। बफ़रड्रेडर एक संसाधन है जिसे कार्यक्रम के साथ समाप्त होने के बाद बंद किया जाना चाहिए:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
} // In this example, the resource declared in the try-with-resources statement is a BufferedReader.

... क्योंकि बफ़र-राइडर उदाहरण एक कोशिश के साथ-साथ स्टेटमेंट में घोषित किया गया है, यह इस बात की परवाह किए बिना बंद कर दिया जाएगा कि ट्राइ स्टेटमेंट सामान्य रूप से पूरा होता है या अचानक (विधि के परिणामस्वरूप बफ़रडेडर.डरलाइन एक IOException फेंकते हुए)।

संपादित करें

नए संपादित प्रश्न के बारे में:

जावा 6 में कोड निष्पादित करता है catch और बाद में finallyब्लॉक को । इसके कारण संसाधन catchब्लॉक में संभावित रूप से खुले रहते हैं ।

जावा 7 सिंटैक्स में, संसाधनों को पहले बंद कर दिया जाता हैcatch ब्लॉक, इसलिए संसाधनों को पहले से ही दौरान बंद हो जाती हैं catchब्लॉक निष्पादन। यह उपरोक्त लिंक में प्रलेखित है:

एक कोशिश के साथ संसाधनों के बयान में, किसी भी कैच या अंततः ब्लॉक को बंद कर दिया जाता है क्योंकि घोषित संसाधनों को बंद कर दिया गया है।


69

कोशिश-के-संसाधनों के साथ आपका उपयोग इस विशेष मामले में ठीक काम करेगा, लेकिन यह सामान्य रूप से बिल्कुल सही नहीं है। आपको संसाधनों को उस तरह से श्रृंखलाबद्ध नहीं करना चाहिए क्योंकि इससे अप्रिय आश्चर्य हो सकता है। मान लें कि आपके पास एक चर बफर आकार है:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
    int sz = /* get buffer size somehow */
    try (BufferedReader br = new BufferedReader(new FileReader(filePath), sz))
    {
        return read(br);
    } 
}

मान लें कि कुछ गलत हुआ और आप szनकारात्मक हो गए। इस स्थिति में आपका फ़ाइल संसाधन (द्वारा बनाया गया new FileReader(filePath)) बंद नहीं होगा।

इस समस्या से बचने के लिए आपको प्रत्येक संसाधन को इस तरह अलग से निर्दिष्ट करना चाहिए:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
    int sz = /* get buffer size somehow */
    try (FileReader file = new FileReader(filePath);
         BufferedReader br = new BufferedReader(file, sz))
    {
        return read(br);
    } 
}

इस मामले में भले ही प्रारंभ की brविफल रहता है fileअभी भी बंद कर दिया जाता है। आप और अधिक जानकारी प्राप्त कर सकते यहाँ और यहाँ


मैं यह समझने की कोशिश कर रहा हूं कि जब sz ऋणात्मक new FileReader(filePath))होता है , तो संसाधन को किस स्थिति में बंद नहीं किया जाता IllegalArgumentExceptionहै। क्या AutoClosableकिसी भी अपवाद के बावजूद सभी संसाधनों को बंद करने की कोशिश नहीं की जाती है?
प्रसून जोशी

3
@PrasoonJoshi नहीं, यह केवल .close()उन वेरिएबल्स के लिए कहता है, जिन्हें ट्राइब के साथ संसाधनों के इनिशियलाइज़र में घोषित किया गया है। इसीलिए इस उदाहरण में इसे दो घोषणाओं में अलग करना चालबाजी करता है।
मारियो कार्नेइरो

4
Andrii और @Mario आप सही और गलत दोनों हैं। पहले उदाहरण में, FileReader को प्रयास-संसाधन तर्क से बंद नहीं किया गया है। लेकिन जब BufferedReader बंद हो जाता है, तो यह लिपटे FileReader को भी बंद कर देगा। प्रमाण के लिए, java.io.BufferedReader.close () के स्रोत पर एक नज़र डालें। परिणामस्वरूप, पहले उदाहरण के कोड को प्राथमिकता दी जानी चाहिए, क्योंकि यह अधिक संक्षिप्त है।
jschreiner

7
@jschreiner ट्रू, हालांकि एंड्री का (कुछ हद तक विवादित) मुद्दा जिसमें sz < 0कंस्ट्रक्टर अपवाद को फेंकने का कारण बनता है, वास्तव में संसाधन को लीक करने का कारण होगा।
मारियो कार्नेइरो

5
@ मोरियो मैं सहमत हूँ। बाहरी कंस्ट्रक्टर विफल हो सकता है, और आंतरिक संसाधन लीक हो जाएगा। मैंने उसे पहले नहीं देखा, धन्यवाद।
jschreiner 20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.