अनावश्यक ऑब्जेक्ट बनाने के मामले
new String() का उपयोग
स्ट्रिंग a, b, c सभी "hi" स्ट्रिंग रखते हैं। हालाँकि, ये तीनों स्ट्रिंग जिन एड्रेस को रेफर करती हैं, वे सभी अलग-अलग हैं, इसलिए समान डेटा के लिए अलग-अलग मेमोरी आवंटित करने की बर्बादी होती है।
<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa53d14aa-6abf-40f0-8441-435647d172fa%2FUntitled.png?table=block&id=f168859c-367c-4924-a4c6-5e04788fab67&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/1146;" width="2000" height="1146"></span>
इसलिए, स्ट्रिंग को घोषित करते समय, new कीवर्ड का उपयोग करने के बजाय, लिटरल का उपयोग करके घोषित करना चाहिए।
उपरोक्त स्रोत कोड केवल एक उदाहरण का उपयोग करता है। इसके अलावा, इस पद्धति का उपयोग करके, यह सुनिश्चित किया जाता है कि एक ही JVM में "hi" स्ट्रिंग लिटरल का उपयोग करने वाले सभी कोड समान ऑब्जेक्ट का पुन: उपयोग करते हैं। ऐसा Java स्थिरांक पूल की विशेषता के कारण है।
new Boolean() का उपयोग
उपरोक्त कोड स्ट्रिंग को पैरामीटर के रूप में लेने वाले कंस्ट्रक्टर के माध्यम से बूलियन इंस्टेंस बना रहा है। बूलियन में केवल सही या गलत होता है, और हर बार इंस्टेंस बनाना मेमोरी की बर्बादी है। इसलिए, Boolean.valueOf() नामक स्थिर फैक्ट्री मेथड का उपयोग करना बेहतर है।
String.matches() का उपयोग
यदि निर्माण लागत अधिक है, तो इसे कैश करके पुन: उपयोग करना बेहतर है, लेकिन हम हमेशा अपने द्वारा बनाए जा रहे ऑब्जेक्ट की लागत नहीं जान सकते हैं। उदाहरण के लिए, यदि आप एक विधि लिखना चाहते हैं जो जांचती है कि दी गई स्ट्रिंग एक वैध रोमन संख्या है या नहीं, तो नियमित अभिव्यक्ति का उपयोग करना सबसे आसान है।
हालांकि, String.matches() प्रदर्शन के मामले में समस्याग्रस्त विधि है। यह विधि आंतरिक रूप से नियमित अभिव्यक्ति पैटर्न इंस्टेंस बनाती है, जिसका उपयोग एक बार किया जाता है और फिर तुरंत कचरा संग्रह का लक्ष्य बन जाता है, और यदि नियमित अभिव्यक्ति का बार-बार उपयोग किया जाता है, तो समान पैटर्न इंस्टेंस बनाया और त्याग दिया जाता है, जिससे लागत बढ़ जाती है। इसलिए, पैटर्न इंस्टेंस को पहले से कैश करना और बाद में isRomanNumeral() विधि को कॉल करते समय उस इंस्टेंस का पुन: उपयोग करना बेहतर है।
**ध्यान दें**
उपरोक्त सभी उदाहरणों में, जब अनावश्यक ऑब्जेक्ट को कैश किया जाता है, तो सभी को अपरिवर्तनीय ऑब्जेक्ट के रूप में बनाया जाता है। ऐसा इसलिए है क्योंकि उन्हें पुन: उपयोग करना सुरक्षित है। हालांकि, अपरिवर्तनीय ऑब्जेक्ट का पुन: उपयोग करने का यह अंतर्ज्ञान कभी-कभी विपरीत होता है।
एडेप्टर (व्यू) एक ऑब्जेक्ट है जो वास्तविक कार्य को बैकएंड ऑब्जेक्ट को सौंपता है और स्वयं एक दूसरा इंटरफ़ेस की भूमिका निभाता है। एडेप्टर को केवल बैकएंड ऑब्जेक्ट का प्रबंधन करने की आवश्यकता होती है, इसलिए प्रत्येक बैकएंड ऑब्जेक्ट के लिए केवल एक एडेप्टर बनाया जाना चाहिए।
उदाहरण के लिए, Map इंटरफ़ेस का keySet() मेथड Map ऑब्जेक्ट के अंदर मौजूद सभी कुंजियों वाला Set व्यू लौटाता है। उपयोगकर्ता सोच सकता है कि keySet() मेथड को कॉल करने पर हर बार एक नया Set इंस्टेंस बनाया जाता है, लेकिन वास्तव में JDK कार्यान्वयन को देखने पर, यह हर बार समान परिवर्तनशील Set इंस्टेंस लौटाता है।
ऐसा इसलिए है क्योंकि लौटाया गया Set इंस्टेंस परिवर्तनशील हो सकता है, लेकिन यह जो कार्य करता है वह समान है, और सभी Set इंस्टेंस Map इंस्टेंस का प्रतिनिधित्व करते हैं। इसलिए, भले ही keySet() कई व्यू ऑब्जेक्ट बनाता है, इससे कोई फर्क नहीं पड़ता, और ऐसा करने का कोई फायदा नहीं है।
इसलिए, यदि आप names1 इंस्टेंस को संशोधित करते हैं, तो names2 इंस्टेंस भी प्रभावित होगा।
हालांकि, व्यक्तिगत रूप से, मुझे लगता है कि keySet() विधि का रिटर्न मान डिफेंसिव कॉपी का उपयोग करके हर बार एक नया ऑब्जेक्ट लौटाना चाहिए। यदि keySet() विधि से प्राप्त Set इंस्टेंस का उपयोग कहीं और किया जा रहा है और उस इंस्टेंस की स्थिति को बदलने वाला कोई कोड है, तो वर्तमान में उपयोग किए जा रहे Set इंस्टेंस और Map इंस्टेंस के मानों पर विश्वास करना मुश्किल हो जाएगा।
इसके अलावा, ऐसे वातावरण में जहां keySet() का अत्यधिक उपयोग नहीं किया जाता है, Set इंटरफ़ेस का हर बार निर्माण प्रदर्शन को गंभीर रूप से प्रभावित नहीं करेगा। इसके बजाय, Set इंटरफ़ेस को अपरिवर्तनीय ऑब्जेक्ट के रूप में बनाना और रखरखाव को सुरक्षित बनाना बेहतर है।
ऑटो बॉक्सिंग
ऑटो बॉक्सिंग एक तकनीक है जो प्रोग्रामर को मूल प्रकार और रैपर प्रकार को मिलाकर उपयोग करने पर स्वचालित रूप से एक दूसरे में परिवर्तित कर देती है। हालाँकि, ऑटो बॉक्सिंग मूल प्रकार और रैपर प्रकार के बीच अंतर को धुंधला कर देता है, लेकिन इसे पूरी तरह से समाप्त नहीं करता है।
तार्किक रूप से, इसमें कोई समस्या नहीं है, लेकिन यह प्रदर्शन के मामले में बहुत अकुशल कोड है। इसका कारण sum के प्रकार और for लूप के अंदर i के प्रकार में है।
sum का प्रकार Long है, और i का प्रकार long है। दूसरे शब्दों में, जब long प्रकार का i पुनरावृति करते समय sum में जोड़ा जाता है, तो हर बार एक नया Long इंस्टेंस बनाया जाता है। नतीजतन, रैपर प्रकार की तुलना में मूल प्रकार का उपयोग करना और अनपेक्षित ऑटो बॉक्सिंग से सावधान रहना महत्वपूर्ण है।
जिसे गलत नहीं समझना चाहिए
अनावश्यक ऑब्जेक्ट निर्माण से बचने के निर्देश को केवल इस तरह से नहीं समझना चाहिए कि ऑब्जेक्ट निर्माण की लागत अधिक है, इसलिए इससे बचना चाहिए।
विशेष रूप से, आजकल JVM में, छोटे ऑब्जेक्ट जो अनावश्यक रूप से बनाए गए हैं, उन्हें बनाना और पुनः प्राप्त करना कोई बड़ी समस्या नहीं है। इसलिए, डेटाबेस कनेक्शन जैसे ऑब्जेक्ट जिनकी लागत बहुत अधिक होती है, को छोड़कर, कस्टम ऑब्जेक्ट पूल न बनाएं।
इसके अलावा, याद रखें कि जब ऑब्जेक्ट को पुन: उपयोग करने के लिए डिफेंसिव कॉपी की आवश्यकता होती है, तो ऑब्जेक्ट को पुन: उपयोग करने से होने वाले नुकसान अनावश्यक ऑब्जेक्ट को बार-बार बनाने से होने वाले नुकसान से कहीं अधिक होते हैं। दोहराए जाने वाले निर्माण का प्रतिकूल प्रभाव केवल कोड के रूप और प्रदर्शन को प्रभावित करता है, लेकिन यदि डिफेंसिव कॉपी विफल हो जाती है, तो यह सीधे बग और सुरक्षा समस्याओं की ओर ले जाती है।
टिप्पणियाँ0