इस पोस्ट के अनुसार , हमें कभी भी अंतिम पद्धति पर भरोसा नहीं करना चाहिए। तो जावा ने इसे प्रोग्रामिंग भाषा में आखिर क्यों शामिल किया?
यह किसी भी प्रोग्रामिंग भाषा को एक फ़ंक्शन में शामिल करने के लिए एक भयानक निर्णय की तरह लगता है जिसे कहा जा सकता है ।
इस पोस्ट के अनुसार , हमें कभी भी अंतिम पद्धति पर भरोसा नहीं करना चाहिए। तो जावा ने इसे प्रोग्रामिंग भाषा में आखिर क्यों शामिल किया?
यह किसी भी प्रोग्रामिंग भाषा को एक फ़ंक्शन में शामिल करने के लिए एक भयानक निर्णय की तरह लगता है जिसे कहा जा सकता है ।
जवाबों:
जोशुआ बलोच के प्रभावी जावा (द्वितीय संस्करण) के अनुसार, finalize()उपयोगी होने पर दो परिदृश्य हैं :
यदि किसी वस्तु का मालिक अपनी स्पष्ट समाप्ति पद्धति को कॉल करना भूल जाता है तो "सुरक्षा जाल" के रूप में कार्य करना है। हालांकि इस बात की कोई गारंटी नहीं है कि फाइनल को तुरंत लागू किया जाएगा, संसाधन को देर से मुक्त करने के लिए बेहतर हो सकता है, उन (उम्मीद दुर्लभ) मामलों में जब क्लाइंट स्पष्ट समाप्ति पद्धति को कॉल करने में विफल रहता है। लेकिन अंतिम रूप से एक चेतावनी को लॉग करना चाहिए यदि यह पाता है कि संसाधन समाप्त नहीं हुआ है
फाइनल का एक दूसरा वैध उपयोग मूल साथियों के साथ वस्तुओं की चिंता करता है। एक देशी सहकर्मी एक देशी वस्तु है जिसमें एक सामान्य वस्तु देशी तरीकों के माध्यम से प्रतिनिधि होती है। क्योंकि एक देशी सहकर्मी एक सामान्य वस्तु नहीं है, कचरा संग्रहकर्ता को इसके बारे में पता नहीं है और जब इसका जावा सहकर्मी पुनः प्राप्त किया जाता है तो इसे पुनः प्राप्त नहीं कर सकता है। इस कार्य को करने के लिए एक अंतिम उपकरण एक उपयुक्त वाहन है, यह मानते हुए कि मूल निवासी कोई महत्वपूर्ण संसाधन नहीं रखता है। यदि देशी सहकर्मी के पास ऐसे संसाधन हैं, जिन्हें तुरंत समाप्त किया जाना चाहिए, तो कक्षा में एक स्पष्ट समाप्ति विधि होनी चाहिए, जैसा कि ऊपर वर्णित है। समाप्ति विधि महत्वपूर्ण संसाधन को मुक्त करने के लिए जो कुछ भी आवश्यक है उसे करना चाहिए।
आगे पढ़ने के लिए, आइटम 7, पृष्ठ 27 का संदर्भ लें।
मूल संसाधनों के प्रबंधन के लिए अंतिम रूप महत्वपूर्ण हैं। उदाहरण के लिए, आपकी ऑब्जेक्ट को गैर-जावा एपीआई का उपयोग करके ऑपरेटिंग सिस्टम से एक विजेटहैंडल आवंटित करने की आवश्यकता हो सकती है। यदि आप उस विजेट को रिलीज़ नहीं करते हैं, जब आपकी ऑब्जेक्ट GC'd है, तो आप WidgetHandles को लीक करने जा रहे हैं।
यह महत्वपूर्ण है कि "फ़ाइनलीज़र को कभी नहीं बुलाया जाता है" मामले केवल नीचे नहीं टूटते हैं:
इन तीनों मामलों में, आपके पास या तो देशी रिसाव नहीं है (इस तथ्य के आधार पर कि आपका कार्यक्रम अब नहीं चल रहा है), या आपके पास पहले से ही एक गैर-देशी रिसाव है (यदि आप प्रबंधित वस्तुओं को उनके बिना आवंटित करते रहते हैं GC'd)।
"चेतावनी कहे जाने वाले फाइनलर पर भरोसा न करें" वास्तव में प्रोग्राम लॉजिक के लिए फाइनलर्स का उपयोग नहीं करने के बारे में है। उदाहरण के लिए, आप अपने प्रोग्राम में सभी चीजों के कितने उदाहरण मौजूद हैं, इस पर नज़र नहीं रखना चाहते हैं कि निर्माण के दौरान किसी फ़ाइल में एक काउंटर बढ़ाकर और इसे एक अंतिम रूप में घटाकर - क्योंकि आपकी वस्तुओं की कोई गारंटी नहीं है। अंतिम रूप दिया जाए, यह फ़ाइल काउंटर शायद कभी भी वापस 0 पर नहीं जाएगा। यह वास्तव में अधिक सामान्य सिद्धांत का एक विशेष मामला है जिसे आपको सामान्य रूप से समाप्त होने वाले अपने कार्यक्रम पर निर्भर नहीं होना चाहिए (पावर विफलताएं, आदि)।
देशी संसाधनों के प्रबंधन के लिए, हालांकि, उन मामलों में जहां अंतिमकारण उन मामलों के अनुरूप नहीं है जहां आप परवाह नहीं करते हैं अगर यह नहीं चलता है।
close()जाता है, तो यह अंतिम रूप से कमबैक है (इसे अनुपलब्ध होने से पहले कभी नहीं बुलाया गया)
इस विधि का उद्देश्य एपीआई प्रलेखन में बताया गया है:
यदि जावा वर्चुअल मशीन ने यह निर्धारित कर लिया है कि उसका कोई साधन नहीं है, जिसके द्वारा इस ऑब्जेक्ट को किसी भी धागे से एक्सेस किया जा सकता है, जो अब तक मर नहीं गया है, तो इसके अलावा, किसी अन्य वस्तु के अंतिम रूप से किए गए कार्य के परिणामस्वरूप या वर्ग जो अंतिम रूप देने के लिए तैयार है ...
finalize... का सामान्य उद्देश्य यह है कि ऑब्जेक्ट को गलत तरीके से त्यागने से पहले सफाई कार्रवाई करना । उदाहरण के लिए, एक इनपुट / आउटपुट कनेक्शन का प्रतिनिधित्व करने वाली किसी वस्तु के लिए अंतिम विधि स्पष्ट रूप से ऑब्जेक्ट को स्थायी रूप से छोड़ने से पहले कनेक्शन को तोड़ने के लिए स्पष्ट I / O लेनदेन कर सकती है ...
यदि आप अतिरिक्त रूप से उन कारणों में रुचि रखते हैं, जिनकी वजह से भाषा डिज़ाइनरों ने चुना है कि "वस्तु बिलकुल ख़राब हो गई है" ( कचरा एकत्र ) जो कि प्रोग्राम प्रोग्रामर कंट्रोल से परे है ("हमें कभी भी भरोसा नहीं करना चाहिए"), इससे संबंधित उत्तर में समझाया गया है प्रश्न :
स्वचालित कचरा संग्रह ... प्रोग्रामिंग त्रुटियों के पूरे वर्गों को समाप्त करता है जो कि बेडवेइल सी और सी ++ प्रोग्रामर हैं। आप जावा कोड को इस विश्वास के साथ विकसित कर सकते हैं कि सिस्टम को कई त्रुटियां जल्दी मिलेंगी और जब तक आपका उत्पादन कोड समाप्त नहीं हो जाता है, तब तक बड़ी समस्याएं निष्क्रिय नहीं होंगी।
उपरोक्त उद्धरण, बदले में, जावा डिजाइन लक्ष्यों के बारे में आधिकारिक दस्तावेज से लिया गया था , यह है कि यह आधिकारिक संदर्भ समझा जा सकता है कि जावा भाषा डिजाइनरों ने इस तरह से क्यों फैसला किया।
इस वरीयता की अधिक विस्तृत और भाषा अज्ञेय चर्चा के लिए, OOSC खंड 9.6 स्वचालित स्मृति प्रबंधन का संदर्भ लें (वास्तव में, न केवल यह खंड बल्कि पूरे अध्याय 9 बहुत पढ़ने योग्य है यदि आप उस तरह के सामान में रुचि रखते हैं)। यह खंड असंदिग्ध कथन के साथ खुलता है:
एक अच्छा OO पर्यावरण को एक स्वचालित मेमोरी प्रबंधन तंत्र की पेशकश करनी चाहिए जो अप्राप्य वस्तुओं का पता लगाएगा और पुनः प्राप्त कर सकता है, जिससे एप्लिकेशन डेवलपर्स को अपनी नौकरी - एप्लिकेशन विकास पर ध्यान केंद्रित करने की अनुमति मिलेगी।
पूर्ववर्ती चर्चा यह दिखाने के लिए पर्याप्त होनी चाहिए कि इस तरह की सुविधा उपलब्ध होना कितना महत्वपूर्ण है। माइकल श्वित्जर और लैंबर्ट स्ट्रेथर के शब्दों में:
स्वचालित मेमोरी प्रबंधन के बिना एक वस्तु-उन्मुख कार्यक्रम लगभग एक सुरक्षा कुकर के बिना प्रेशर कुकर के समान है: जितनी जल्दी या बाद में बात उड़ा देना सुनिश्चित है!
अंतिम रूप से मौजूद हैं क्योंकि उन्हें यह सुनिश्चित करने का एक प्रभावी साधन होने की उम्मीद थी कि चीजें साफ हो जाएं (भले ही वे व्यवहार में न हों), और क्योंकि जब उनका आविष्कार किया गया था, तो सफाई सुनिश्चित करने के बेहतर साधन (जैसे कि प्रेत संदर्भ और कोशिश के साथ) -सूत्र) अभी तक मौजूद नहीं थे। यदि आपकी शुरुआत में "अंतिम रूप" की सुविधा को लागू करने के लिए खर्च किए गए थे, तो जावा बेहतर होगा, सफाई के अन्य साधनों पर खर्च किया गया था, लेकिन जावा शुरू में विकसित होने के समय शायद ही स्पष्ट था।
गुफा: मैं पुराना हो सकता हूं, लेकिन यह कुछ साल पहले की मेरी समझ है:
सामान्य तौर पर, जब कोई फ़ाइनलीज़र चलता है - या यहां तक कि यह बिल्कुल भी चलता है, इसकी कोई गारंटी नहीं है, हालांकि कुछ जेवीएम आपको कार्यक्रम से बाहर निकलने से पहले एक पूर्ण जीसी और अंतिम रूप देने का अनुरोध करने देंगे (जो, ज़ाहिर है, इसका मतलब है कि कार्यक्रम में अधिक समय लगता है बाहर निकलने के लिए, और जो ऑपरेशन का डिफ़ॉल्ट मोड नहीं है)।
और कुछ GCs को स्पष्ट रूप से देरी या GC'ing ऑब्जेक्ट्स से बचने के लिए जाना जाता था जिनके पास अंतिम रूप था, इस उम्मीद में कि यह बेंचमार्क में बेहतर प्रदर्शन का उत्पादन करेगा।
इन व्यवहारों से दुर्भाग्य से मूल कारणों के साथ संघर्ष की सिफारिश की गई थी, और इसके बजाय स्पष्ट रूप से शटडाउन विधियों के उपयोग को प्रोत्साहित किया गया था।
यदि आपके पास एक ऐसी वस्तु है जिसे वास्तव में त्यागने से पहले साफ करना है, और यदि आप वास्तव में ऐसा करने के लिए उपयोगकर्ताओं पर भरोसा नहीं कर सकते हैं, तो एक अंतिम रूप अभी भी विचार करने योग्य हो सकता है। लेकिन सामान्य तौर पर, वहाँ अच्छे कारण हैं कि आप उन्हें अक्सर आधुनिक जावा कोड में नहीं देखते हैं जैसा कि आपने कुछ शुरुआती उदाहरणों में किया था।
गूगल जावा स्टाइल गाइड इस विषय पर कुछ ऋषि सलाह है:
यह है अत्यंत दुर्लभ ओवरराइड करने के लिए
Object.finalize।युक्ति : यह मत करो। यदि आप पूरी तरह से, पहले प्रभावी जावा आइटम 7 को पढ़ें और समझें , "फाइनल से बचें," बहुत सावधानी से, और फिर ऐसा न करें।
PhantomReferenceऔर ReferenceQueueइसके बजाय खुद को बनाना चाहते हैं ।
PhantomReferenceहै कि एक बेहतर समाधान है। फाइनलर्स एक मस्सा है जिसे जावा के शुरुआती दिनों से छोड़ दिया जाता है, और जैसे Object.clone()और कच्चे प्रकार, सबसे अच्छी तरह से भूल गए भाषा का हिस्सा हैं।
जावा भाषा विशिष्टता (जावा SE 7) कहती है:
फाइनलर्स उन संसाधनों को मुक्त करने का मौका प्रदान करते हैं जिन्हें स्वचालित स्टोरेज मैनेजर द्वारा स्वचालित रूप से मुक्त नहीं किया जा सकता है। ऐसी स्थितियों में, बस किसी ऑब्जेक्ट द्वारा उपयोग की जाने वाली मेमोरी को पुनः प्राप्त करने की गारंटी नहीं होगी कि इसके द्वारा आयोजित संसाधनों को पुनः प्राप्त किया जाएगा।