"एमिगो, टेन-हट!"

"मैं जावा सीखकर खुश हूँ, कप्तान!"

"आराम से, अमीगो। आज हमारे पास एक सुपर दिलचस्प विषय है। हम इस बारे में बात करेंगे कि जावा प्रोग्राम बाहरी संसाधनों के साथ कैसे इंटरैक्ट करता है और हम एक बहुत ही दिलचस्प जावा स्टेटमेंट का अध्ययन करेंगे। बेहतर होगा कि आप अपने कानों को न ढकें।"

"मेरा कान है।"

"जैसे ही जावा प्रोग्राम चलता है, कभी-कभी यह जावा मशीन के बाहर की संस्थाओं के साथ इंटरैक्ट करता है। उदाहरण के लिए, डिस्क पर फाइलों के साथ। इन संस्थाओं को आमतौर पर बाहरी संसाधन कहा जाता है।"

"फिर आंतरिक संसाधन किसे माना जाता है?"

"आंतरिक संसाधन जावा मशीन के अंदर बनाई गई वस्तुएं हैं। आमतौर पर, बातचीत इस योजना का अनुसरण करती है:

कोशिश-के साथ-संसाधन कथन

"ऑपरेटिंग सिस्टम सख्ती से उपलब्ध संसाधनों का ट्रैक रखता है , और विभिन्न कार्यक्रमों से उन तक साझा पहुंच को भी नियंत्रित करता है। उदाहरण के लिए, यदि एक प्रोग्राम फ़ाइल को बदलता है, तो दूसरा प्रोग्राम उस फ़ाइल को बदल (या हटा नहीं) सकता है। यह सिद्धांत नहीं है फाइलों तक ही सीमित है, लेकिन वे सबसे आसानी से समझने योग्य उदाहरण प्रदान करते हैं।

"ऑपरेटिंग सिस्टम में ऐसे कार्य (एपीआई) होते हैं जो एक प्रोग्राम को संसाधनों को प्राप्त करने और/या जारी करने की अनुमति देते हैं। यदि कोई संसाधन व्यस्त है, तो केवल वह प्रोग्राम जिसने इसे प्राप्त किया है वह इसके साथ काम कर सकता है। यदि कोई संसाधन मुफ़्त है, तो कोई भी प्रोग्राम अधिग्रहण कर सकता है। यह।

"कल्पना कीजिए कि एक कार्यालय ने कॉफी मग साझा किया है। यदि कोई मग लेता है, तो अन्य लोग इसे नहीं ले सकते हैं। लेकिन एक बार मग का उपयोग किया जाता है, धोया जाता है, और वापस अपने स्थान पर रख दिया जाता है, तो कोई भी इसे दोबारा ले सकता है।"

"मिल गया। यह सबवे या अन्य सार्वजनिक परिवहन पर सीटों की तरह है। यदि सीट खाली है, तो कोई भी इसे ले सकता है। यदि सीट पर कब्जा कर लिया गया है, तो इसे लेने वाले व्यक्ति द्वारा नियंत्रित किया जाता है।"

"यह सही है। और अब बाहरी संसाधनों को प्राप्त करने के बारे में बात करते हैं। हर बार जब आपका जावा प्रोग्राम डिस्क पर फ़ाइल के साथ काम करना शुरू करता है, तो जावा मशीन ऑपरेटिंग सिस्टम से इसके लिए विशेष पहुंच के लिए कहती है। यदि संसाधन मुफ्त है, तो जावा मशीन प्राप्त कर लेती है। यह।

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

"यह उचित लगता है।"

"इसे इस तरह रखने के लिए, ऑपरेटिंग सिस्टम प्रत्येक चल रहे प्रोग्राम द्वारा कब्जा किए गए संसाधनों की एक सूची रखता है। यदि आपका प्रोग्राम निर्दिष्ट संसाधन सीमा से अधिक है, तो ऑपरेटिंग सिस्टम अब आपको नए संसाधन नहीं देगा।

"यह उन कार्यक्रमों की तरह है जो सभी मेमोरी खा सकते हैं ..."

"ऐसा कुछ। अच्छी खबर यह है कि यदि आपका प्रोग्राम समाप्त हो जाता है, तो सभी संसाधन स्वचालित रूप से जारी हो जाते हैं (ऑपरेटिंग सिस्टम स्वयं ऐसा करता है)।"

"अगर यह अच्छी खबर है, तो क्या इसका मतलब यह है कि बुरी खबर है?"

"बिल्कुल सही। बुरी खबर यह है कि यदि आप एक सर्वर एप्लिकेशन लिख रहे हैं..."

"लेकिन क्या मैं ऐसे एप्लिकेशन लिखता हूं?"

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

"दूसरे शब्दों में, कार्यक्रम समाप्त नहीं होता है, और इसका मतलब है कि स्मृति स्वचालित रूप से जारी नहीं होती है।"

"बिल्कुल सही। और अगर आप एक दिन में 100 फाइलें खोलते हैं और उन्हें बंद नहीं करते हैं, तो कुछ हफ़्ते में आपका एप्लिकेशन अपनी संसाधन सीमा तक पहुंच जाएगा और क्रैश हो जाएगा।"

"यह स्थिर कार्य के महीनों से बहुत कम हो रहा है! क्या किया जा सकता है?"

"बाहरी संसाधनों का उपयोग करने वाली कक्षाओं में उन्हें जारी करने के लिए एक विशेष विधि होती है: close().

"यहाँ एक प्रोग्राम का उदाहरण दिया गया है जो एक फ़ाइल में कुछ लिखता है और जब यह हो जाता है तो फ़ाइल को बंद कर देता है, अर्थात यह ऑपरेटिंग सिस्टम के संसाधनों को मुक्त करता है। यह मोटे तौर पर इस तरह दिखता है:

कोड टिप्पणी
String path = "c:\\projects\\log.txt";
FileOutputStream output = new FileOutputStream(path);
output.write(1);
output.close();
फ़ाइल का पथ।
फ़ाइल ऑब्जेक्ट प्राप्त करें: संसाधन प्राप्त करें।
फ़ाइल में लिखें
फ़ाइल बंद करें - संसाधन जारी करें

"आह... तो, एक फ़ाइल (या अन्य बाहरी संसाधनों) के साथ काम करने के बाद, मुझे close()बाहरी संसाधन से जुड़ी वस्तु पर विधि को कॉल करना होगा।"

"हाँ। यह सब सरल लगता है। लेकिन एक कार्यक्रम के चलते अपवाद हो सकते हैं, और बाहरी संसाधन जारी नहीं होंगे।"

"और यह बहुत बुरा है। क्या करें?"

"यह सुनिश्चित करने के लिए कि विधि हमेशा कॉल की जाती है, हमें अपने कोड को - - ब्लॉक close()में लपेटना होगा और विधि को ब्लॉक में जोड़ना होगा । यह कुछ इस तरह दिखाई देगा:trycatchfinallyclose()finally

try
{
   FileOutputStream output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

"हम्म... यहाँ कुछ गड़बड़ है?"

"ठीक है। यह कोड संकलित नहीं होगा, क्योंकि outputचर ब्लॉक के अंदर घोषित किया गया है , और इसलिए ब्लॉक try{}में दिखाई नहीं दे रहा है ।finally

आइए इसे ठीक करें:

FileOutputStream output = new FileOutputStream(path);

try
{
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

"क्या अब सब ठीक है?"

"यह ठीक है, लेकिन अगर हम वस्तु बनाते समय कोई त्रुटि होती है तो यह काम नहीं करेगा FileOutputStream, और यह काफी आसानी से हो सकता है।

आइए इसे ठीक करें:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
   output.close();
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   output.close();
}

"और क्या अब सब कुछ काम करता है?"

"अभी भी कुछ आलोचनाएँ हैं। सबसे पहले, यदि FileOutputStreamऑब्जेक्ट बनाते समय कोई त्रुटि होती है, तो outputचर शून्य हो जाएगा। इस संभावना को finallyब्लॉक में शामिल किया जाना चाहिए।

"दूसरा, close()विधि को हमेशा finallyब्लॉक में कहा जाता है, जिसका अर्थ है कि यह tryब्लॉक में आवश्यक नहीं है। अंतिम कोड इस तरह दिखेगा:

FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
catch (IOException e)
{
   e.printStackTrace();
}
finally
{
   if (output!=null)
      output.close();
}

"यहां तक ​​​​कि अगर हम ब्लॉक पर विचार नहीं करते हैं catch, जिसे छोड़ा जा सकता है, तो हमारे कोड की 3 पंक्तियां 10 बन जाती हैं। लेकिन हमने मूल रूप से फ़ाइल खोली और 1 लिखा।"

"ओफ़्फ़... यह अच्छी बात है कि बात समाप्त हो गई। अपेक्षाकृत समझने योग्य, लेकिन कुछ हद तक थकाऊ, है न?"

"तो यह है। यही कारण है कि जावा के रचनाकारों ने कुछ सिंटैक्टिक चीनी जोड़कर हमारी मदद की। अब चलो कार्यक्रम की हाइलाइट पर चलते हैं, या बल्कि, यह पाठ:

try-संसाधनों के साथ

"अपने 7वें संस्करण से शुरू करते हुए, जावा के पास एक नया try-संसाधनों के साथ कथन है।

"यह विधि को अनिवार्य कॉल के साथ समस्या को ठीक करने के लिए बनाया गया था close()।"

"यह आशाजनक लगता है!"

"सामान्य मामला काफी सरल दिखता है:

try (ClassName name = new ClassName())
{
   Code that works with the name variable
}

"तो यह try बयान का एक और रूपांतर है ?"

"हाँ। आपको tryकीवर्ड के बाद कोष्ठक जोड़ने की आवश्यकता है, और फिर कोष्ठक के अंदर बाहरी संसाधनों के साथ ऑब्जेक्ट बनाने की आवश्यकता है। कोष्ठक में प्रत्येक वस्तु के लिए, कंपाइलर एक सेक्शन और विधि finallyको कॉल जोड़ता है।close()

"नीचे दो समकक्ष उदाहरण हैं:

लंबा कोड कोशिश-के-संसाधनों के साथ कोड
FileOutputStream output = null;

try
{
   output = new FileOutputStream(path);
   output.write(1);
}
finally
{
   if (output!=null)
   output.close();
}
try(FileOutputStream output = new FileOutputStream(path))
{
   output.write(1);
}

try"कूल! -with-resources का उपयोग करने वाला कोड बहुत छोटा और पढ़ने में आसान है। और हमारे पास जितना कम कोड होगा, टाइपो या अन्य त्रुटि होने की संभावना उतनी ही कम होगी।"

"मुझे खुशी है कि आपको यह पसंद आया। वैसे, हम -with-resources स्टेटमेंट में जोड़ catchऔर finallyब्लॉक कर सकते हैं try। या यदि उनकी आवश्यकता नहीं है तो आप उन्हें नहीं जोड़ सकते।

एक ही समय में कई चर

"आप अक्सर एक ऐसी स्थिति का सामना कर सकते हैं जब आपको एक ही समय में कई फाइलें खोलने की आवश्यकता होती है। मान लीजिए कि आप एक फ़ाइल की प्रतिलिपि बना रहे हैं, इसलिए आपको दो वस्तुओं की आवश्यकता है: वह फ़ाइल जिससे आप डेटा कॉपी कर रहे हैं और वह फ़ाइल जिसमें आप डेटा कॉपी कर रहे हैं .

"इस मामले में, try-with-resources स्टेटमेंट आपको इसमें एक लेकिन कई ऑब्जेक्ट बनाने देता है। ऑब्जेक्ट बनाने वाले कोड को अर्धविराम से अलग किया जाना चाहिए। यहां इस स्टेटमेंट का सामान्य स्वरूप है:

try (ClassName name = new ClassName(); ClassName2 name2 = new ClassName2())
{
   Code that works with the name and name2 variables
}

फ़ाइलों की प्रतिलिपि बनाने का उदाहरण:

लघु कूट संख्या लंबा कोड
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);

FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

FileInputStream input = null;
FileOutputStream output = null;

try
{
   input = new FileInputStream(src);
   output = new FileOutputStream(dest);

   byte[] buffer = input.readAllBytes();
   output.write(buffer);
}
finally
{
   if (input!=null)
      input.close();
   if (output!=null)
      output.close();
}

"ठीक है, हम यहाँ क्या कह सकते हैं? try-संसाधनों के साथ एक अद्भुत बात है!"

"हम क्या कह सकते हैं कि हमें इसका इस्तेमाल करना चाहिए।"