लागू करने योग्य या बंद करने के लिए लागू


128

मैं जावा सीखने की प्रक्रिया में हूं और मुझे implements Closeableऔर implements AutoCloseableइंटरफेस पर कोई अच्छी व्याख्या नहीं मिल रही है।

जब मैंने interface Closeableए लागू किया , तो मेरी ग्रहण आईडीई ने एक विधि बनाई public void close() throws IOException

मैं pw.close();इंटरफ़ेस के बिना स्ट्रीम को बंद कर सकता हूं । लेकिन, मैं यह नहीं समझ सकता कि मैं close()इंटरफ़ेस का उपयोग करके विधि को कैसे लागू कर सकता हूं । और, इस इंटरफ़ेस का उद्देश्य क्या है?

इसके अलावा मैं जानना चाहूंगा: अगर मैं IOstreamवास्तव में बंद था तो मैं कैसे जांच सकता हूं ?

मैं नीचे मूल कोड का उपयोग कर रहा था

import java.io.*;

public class IOtest implements AutoCloseable {

public static void main(String[] args) throws IOException  {

    File file = new File("C:\\test.txt");
    PrintWriter pw = new PrintWriter(file);

    System.out.println("file has been created");

    pw.println("file has been created");

}

@Override
public void close() throws IOException {


}

2
मुझे लगता है कि सभी पहले ही कहा जा चुका है, लेकिन हो सकता है कि आप निम्नलिखित लेखों में रुचि के बारे में प्रयास करने के बारे में रुचि रखते हों: docs.oracle.com/javase/tutorial/essential/exception/… । यह दिए गए उत्तरों को समझने में भी सहायक हो सकता है।
क्रुसम

जवाबों:


40

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

आपको केवल (या चाहिए) को लागू करना होगा Closeableया AutoCloseableयदि आप अपने स्वयं के कार्यान्वयन के बारे में हैं PrintWriter, जो फ़ाइलों या किसी अन्य संसाधन को संभालता है जिसे बंद करने की आवश्यकता है।

आपके कार्यान्वयन में, यह कॉल करने के लिए पर्याप्त है pw.close()। आपको इसे आखिरकार ब्लॉक में करना चाहिए:

PrintWriter pw = null;
try {
   File file = new File("C:\\test.txt");
   pw = new PrintWriter(file);
} catch (IOException e) {
   System.out.println("bad things happen");
} finally {
   if (pw != null) {
      try {
         pw.close();
      } catch (IOException e) {
      }
   }
}

उपरोक्त कोड जावा 6 संबंधित है। जावा 7 में यह अधिक सुरुचिपूर्ण ढंग से किया जा सकता है ( इस उत्तर को देखें )।


3
केवल ए के साथ ही क्यों PrintWriter? विशेष रूप से AutoClosableवस्तुओं का उपयोग सिर्फ PrintWriterएस की तुलना में कई और परिस्थितियों में किया जा सकता है ...
14

3
तुम पूरी तरह ठीक हो। प्रश्न इस बारे में था PrintWriterइसलिए मैंने इसे अधिक विशिष्ट होने का उल्लेख किया।
काई

7
जावा 6 की स्थिति के संदर्भ में वर्णन क्यों करें AutoCloseable? बेहतर दिखाने के लिए एक try-with-resourcesके बजाय ...
ᴠɪɴᴄᴇɴᴛ

191

AutoCloseable(जावा 7 में पेश किया गया) कोशिश-संसाधनों के मुहावरे का उपयोग करना संभव बनाता है :

public class MyResource implements AutoCloseable {

    public void close() throws Exception {
        System.out.println("Closing!");
    }

}

अब आप कह सकते हैं:

try (MyResource res = new MyResource()) {
    // use resource here
}

और JVM close()आपके लिए अपने आप कॉल करेगा।

Closeable पुराना इंटरफ़ेस है। किसी कारण के लिएपिछड़े संगतता को बनाए रखने के लिए, भाषा डिजाइनरों ने एक अलग बनाने का फैसला किया। यह न केवल सभी Closeableवर्गों (जैसे धाराओं को फेंकने IOException) को कोशिश-के-संसाधनों में उपयोग करने की अनुमति देता है, बल्कि इससे अधिक सामान्य जाँच किए गए अपवादों को भी फेंकने की अनुमति देता है close()

जब संदेह, उपयोग AutoCloseable, आपकी कक्षा के उपयोगकर्ता आभारी होंगे।


107
कारण सरल है: Closeable.close()फेंकता है IOException। बहुत सारे close()तरीके, जो कोशिश-के-संसाधनों का लाभ उठा सकते हैं, अन्य जाँच किए गए अपवादों को फेंक देते हैं (जैसे कि java.sql.Connection.close()इतना AutoCloseable.close()फेंकता है Exception। मौजूदा Closeableअनुबंध को बदलना सभी मौजूदा अनुप्रयोगों / लाइब्रेरी को अनुबंध पर निर्भर करता है जो close()केवल फेंकता है IOExceptionऔर सभी (चेक किए गए) अपवादों को नहीं छोड़ता है।)
मार्क

4
@MarkRotteveel: +1, धन्यवाद। मैंने आपके सुझावों और टिप्पणियों को दर्शाने के लिए अपने उत्तर को सही किया।
टॉमाज़ नर्कविक्ज़

9
और भी: Closeable.close() आवश्यक होना चाहिए। AutoCloseable.close()हालांकि, यह अभी भी दृढ़ता से अनुशंसित है।
लुकास ईडर

2
इसके अलावा, डिफ़ॉल्ट का उपयोग न करें public void close( ) throws Exception - यदि आप कर सकते हैं तो एक अधिक विशिष्ट अपवाद का उपयोग करें (जैसे IOException)
gerardw

3
Closeableआलस्य की गारंटी नहीं देता है । यह आवश्यकता का एक उपयोगकर्ता के क्रियान्वयन में idempotence close()विधि। और क्या IOExceptionअधिक विशिष्ट / उपयुक्त उपयोग के मामले पर निर्भर करता है।
xdhmoore

71

Closeableफैली हुई है AutoCloseable, और विशेष रूप से IO धाराओं के लिए समर्पित है: यह अपवाद के बजाय IOException को फेंकता है, और यह बेकार है, जबकि AutoCloseable इस गारंटी को प्रदान नहीं करता है।

यह सब दोनों इंटरफेस के javadoc में समझाया गया है।

AutoCloseable (या Closeable) को लागू करने से जावा 7 में पेश किए गए संसाधनों के निर्माण के साथ-साथ संसाधनों के निर्माण के लिए एक वर्ग का उपयोग करने की अनुमति मिलती है, जो एक ब्लॉक के अंत में ऐसे संसाधनों को स्वचालित रूप से बंद करने की अनुमति देता है, बिना अंत में ब्लॉक को जोड़ने के बिना। संसाधन सहज रूप से।

आपकी कक्षा एक नज़दीकी संसाधन का प्रतिनिधित्व नहीं करती है, और इस इंटरफ़ेस को लागू करने का कोई मतलब नहीं है: एक IOTest को बंद नहीं किया जा सकता है। यहां तक ​​कि इसे इंस्टेंट करना भी संभव नहीं होना चाहिए, क्योंकि इसमें कोई इंस्टेंस विधि नहीं है। याद रखें कि इंटरफ़ेस लागू करने का मतलब है कि ए वर्ग और इंटरफ़ेस के बीच एक संबंध है। आपका यहां कोई रिश्ता नहीं है।


5
बस धाराओं से संबंधित वर्गों के लिए क्लोजेबल को लागू करें , और ऑटोक्लोसेबल को दूसरों के लिए जो आटोक्लेज़ सुविधा की आवश्यकता होती है।
११:१३ बजे लोपेज जूल

7

यहाँ छोटा उदाहरण है

public class TryWithResource {

    public static void main(String[] args) {
        try (TestMe r = new TestMe()) {
            r.generalTest();
        } catch(Exception e) {
            System.out.println("From Exception Block");
        } finally {
            System.out.println("From Final Block");
        }
    }
}



public class TestMe implements AutoCloseable {

    @Override
    public void close() throws Exception {
        System.out.println(" From Close -  AutoCloseable  ");
    }

    public void generalTest() {
        System.out.println(" GeneralTest ");
    }
}

यहाँ उत्पादन है:

GeneralTest 
From Close -  AutoCloseable  
From Final Block

आउटपुट लिखना भी बेहतर है, इसलिए इस तरह के शॉर्ट कोड के लिए ट्रायल प्रोजेक्ट की जरूरत नहीं होगी।
रक्सेटुल

क्लोज़ () विधि में, क्या हमें संसाधन को स्पष्ट रूप से बंद करने की आवश्यकता नहीं है? शायद केवल प्रिंट स्टेटमेंट है।
शैलेश वाघमारे

@ शीलेश वाघमारे हां बिल्कुल। लेकिन परीक्षण के उद्देश्य से मैंने कोड स्निप में उल्लेख किया है।
लोवा चित्तमुरी

@LovaChittumuri तो यह this.close()कोड में पसंद या कुछ होगा ?, क्योंकि यह स्वचालित रूप से कहा जाता है। (सिर्फ यकीन है कि)
शैलेश वाघमारे

@ शैलेश वाघमारे क्या आप मेरी परीक्षा लेना चाहेंगे।
लोवा चित्तमुरी

6

try-with-resources स्टेटमेंट।

try-with-resources statementएक है tryबयान है कि एक या अधिक संसाधनों की घोषणा की। ए resourceएक ऑब्जेक्ट है जिसे प्रोग्राम के साथ समाप्त होने के बाद बंद किया जाना चाहिए। यह try-with-resources statementसुनिश्चित करता है कि प्रत्येक संसाधन कथन के अंत में बंद है। कोई भी वस्तु जो लागू होती है java.lang.AutoCloseable, जिसमें सभी ऑब्जेक्ट शामिल होते हैं जो लागू होते हैंjava.io.Closeable , एक संसाधन के रूप में उपयोग किया जा सकता है।

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

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

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

जावा एसई 7 से पहले, आप finallyयह सुनिश्चित करने के लिए एक ब्लॉक का उपयोग कर सकते हैं कि प्रयास विवरण सामान्य रूप से या अचानक पूरा होता है या नहीं। निम्नलिखित उदाहरण finallyएक try-with-resourcesबयान के बजाय एक ब्लॉक का उपयोग करता है :

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

}

कृपया डॉक्स को देखें


6

हाल ही में मैंने जावा एसई 8 प्रोग्रामर गाइड ii बुक पढ़ा है।

मुझे AutoCloseableबनाम के बीच के अंतर के बारे में कुछ पता चला Closeable

AutoCloseableइंटरफ़ेस जावा 7. इससे पहले में पेश किया गया था, एक और इंटरफ़ेस बुलाया अस्तित्व Closeable। निम्नलिखित अपवादों के साथ भाषा डिजाइनर क्या चाहते हैं, यह समान था:

  • Closeableअपवाद के प्रकार को प्रतिबंधित करता है IOException
  • Closeable को लागू करने की आवश्यकता है।

भाषा डिजाइनर पिछड़े अनुकूलता पर जोर देते हैं। चूंकि मौजूदा इंटरफ़ेस बदलना अवांछनीय था, इसलिए उन्होंने एक नया नाम दिया AutoCloseable। यह नया इंटरफ़ेस की तुलना में कम सख्त है Closeable। चूंकि , इसके Closeableलिए आवश्यकताओं को पूरा करता है AutoCloseable, इसलिए इसे लागू करना शुरू कर दिया AutoCloseableगया था जब बाद में पेश किया गया था।


1
यह कहने के बजाय कि "यह नया इंटरफ़ेस की तुलना में कम सख्त है Closeable", मैं यह कहना चाहूँगा कि "इस नए इंटरफ़ेस का उपयोग अधिक सामान्य संदर्भों में किया जा सकता है, जहां समापन के दौरान फेंके गए अपवाद आवश्यक रूप से IOException नहीं है"। जावा ब्रह्मांड में, "कम सख्त" होने के कारण इसके बारे में एक नकारात्मक खिंचाव है।
झरने के स्रोतों
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.