java - क्या "नया स्ट्रिंग()" अपरिवर्तनीय भी है?




string immutability (10)

मैं थोड़ी देर के लिए जावा स्ट्रिंग का अध्ययन कर रहा हूं। निम्नलिखित प्रश्न नीचे दिए गए पदों पर आधारित हैं

जावा स्ट्रिंग विशेष है
जावा में स्ट्रिंग की अपरिवर्तनीयता

  1. अपरिवर्तनीयता: अब, अपरिवर्तनीयता से जाकर, स्ट्रिंग क्लास को डिज़ाइन किया गया है ताकि आम पूल में मूल्यों को अन्य स्थानों / चरों में पुन: उपयोग किया जा सके। अगर String को बनाया गया तो यह अच्छा रहता है

    String a = "Hello World!"; हालांकि, अगर मैं स्ट्रिंग की तरह बना देता हूं

    String b = new String("Hello World!"); यह अपरिवर्तनीय क्यों है? (या यह है?)। चूंकि इसमें एक समर्पित ढेर मेमोरी है, इसलिए मुझे किसी भी अन्य चर को प्रभावित किए बिना इसे संशोधित करने में सक्षम होना चाहिए। तो डिजाइन द्वारा, क्या कोई अन्य कारण था कि पूरी तरह से String को अपरिवर्तनीय माना जाता है? या मेरी उपरोक्त धारणा गलत है?

  2. दूसरी बात जो मैं पूछना चाहता था वह सामान्य स्ट्रिंग पूल के बारे में था। अगर मैं एक स्ट्रिंग ऑब्जेक्ट बनाता हूं

    String c = ""; पूल में बनाई गई एक खाली प्रविष्टि है?

क्या इन पर कोई पोस्ट पहले से है? यदि हां, तो क्या कोई लिंक साझा कर सकता है?


स्ट्रिंग अपरिवर्तनीय है चाहे यह तत्काल कैसे हो

1) संक्षिप्त उत्तर हाँ है , new String() भी अपरिवर्तनीय है।

चूंकि String पर आपके द्वारा किए जाने वाले प्रत्येक संभावित toLowerCase ऑपरेशन (जैसे replace , toLowerCase इत्यादि) मूल String इंस्टेंस को प्रभावित नहीं करते हैं और आपको एक नया उदाहरण देता है

आप इसे String लिए जावाडोक में देख सकते हैं। String का प्रत्येक public तरीका जो खुलासा हुआ है, एक नया String इंस्टेंस देता है और उस वर्तमान इंस्टेंस को बदलता नहीं है जिस पर आपने विधि कहा था।

बहु-थ्रेडेड वातावरण में यह बहुत उपयोगी है क्योंकि जब भी आप String पास करते हैं या साझा करते हैं तो आपको उत्परिवर्तन ( कोई मूल्य बदल देगा ) के बारे में सोचना नहीं है। String आसानी से सबसे अधिक इस्तेमाल किया जाने वाला डेटा प्रकार हो सकता है, इसलिए डिजाइनरों ने हमें हर किसी को उत्परिवर्तन के बारे में सोचने के लिए आशीर्वाद नहीं दिया है और हमें बहुत दर्द बचाया है।

अपरिवर्तनीयता स्ट्रिंग पूल या कैशिंग की अनुमति है

यह अपरिवर्तनीय संपत्ति की वजह से है कि स्ट्रिंग का आंतरिक पूल संभव था, क्योंकि जब किसी अन्य स्थान पर समान स्ट्रिंग मान की आवश्यकता होती है तो उस अपरिवर्तनीय संदर्भ को वापस कर दिया जाता है। यदि String म्यूटेबल हो गया होता तो स्मृति को बचाने के लिए String तरह साझा करना संभव नहीं होता।

स्ट्रिंग अपरिवर्तनीयता पूलिंग की वजह से नहीं थी, लेकिन अपरिवर्तनीयता से इसके अधिक लाभ जुड़े हुए हैं।

स्ट्रिंग इंटर्निंग या पूलिंग फ्लाईवेट डिज़ाइन पैटर्न का एक उदाहरण है

2) हां इसे किसी भी अन्य String तरह प्रशिक्षित किया जाएगा क्योंकि रिक्त String भी अन्य String उदाहरणों के रूप में एक String

संदर्भ:


1) अपरिवर्तनीय हिस्सा पूल की वजह से नहीं है; यह पूल को पहले स्थान पर संभव बनाता है। स्ट्रिंग्स को अक्सर अन्य कार्यों के लिए तर्क के रूप में पारित किया जाता है या यहां तक ​​कि अन्य धागे के साथ साझा किया जाता है; स्ट्रिंग्स अपरिवर्तनीय बनाना ऐसी परिस्थितियों में तर्क को आसान बनाने का एक डिज़ाइन निर्णय था। तो हाँ - जावा में String हमेशा अपरिवर्तनीय होते हैं, इससे कोई फर्क नहीं पड़ता कि आप उन्हें कैसे बनाते हैं (ध्यान दें कि जावा में उत्परिवर्तनीय तार होना संभव है - बस String क्लास के साथ नहीं)।

2) हां। शायद। मैं वास्तव में 100% निश्चित नहीं हूं, लेकिन यह मामला होना चाहिए।



अपरिवर्तनीयता new सुविधा नहीं है, यह कक्षा String की एक विशेषता है। इसमें कोई म्यूटेटर विधियां नहीं हैं, इसलिए यह अपरिवर्तनीय है।


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

आप b=b+"x"; का उपयोग कर एक स्ट्रिंग बदल सकते हैं b=b+"x"; या b=new String(b); , और चर की सामग्री को बदलने के लिए प्रतीत होता है, लेकिन एक संदर्भ (यहां परिवर्तनीय b ) की अपरिवर्तनीयता को भ्रमित न करें और जिस वस्तु का जिक्र है (सी में पॉइंटर्स के बारे में सोचें)। जिस वस्तु का संदर्भ इंगित कर रहा है वह उसकी रचना के बाद अपरिवर्तित रहेगा।

यदि आपको ऑब्जेक्ट की सामग्री को बदलने (संदर्भ बदलने के बजाए) स्ट्रिंग को बदलने की आवश्यकता है, तो आप स्ट्रिंगबफर का उपयोग कर सकते हैं, जो स्ट्रिंग का एक परिवर्तनीय संस्करण है।


बनाए गए तार हमेशा इस बात पर ध्यान दिए बिना अपरिवर्तनीय होंगे कि वे कैसे बनाए जाते हैं।

आपके सवालों के जवाब:

  1. केवल अंतर है:
    जब स्ट्रिंग की तरह बनाई जाती है - {String a = "Hello World!";} तो केवल एक ऑब्जेक्ट बन जाता है।
    और जब यह बनाया जाता है - {String b = new String("Hello World!");} तो दो ऑब्जेक्ट्स बन जाते हैं। पहला, क्योंकि आपने स्ट्रिंग प्रॉपर्टी के कारण 'नया' कीवर्ड और दूसरा इस्तेमाल किया है।

  2. जी हां निश्चित तौर पर। पूल में बनाई गई एक खाली प्रविष्टि होगी।


स्ट्रिंग अपरिवर्तनीय साधन है कि आप वस्तु को स्वयं नहीं बदल सकते हैं इससे कोई फर्क नहीं पड़ता कि आपने इसे कैसे बनाया है। और दूसरे प्रश्न के लिए: हाँ यह एक प्रविष्टि बनाएगा।


स्ट्रिंग अपरिवर्तनीय है क्योंकि यह आपको इसे संशोधित करने का मतलब प्रदान नहीं करता है। यह किसी भी छेड़छाड़ से बचने के लिए डिज़ाइन है (यह अंतिम है, अंतर्निहित सरणी को छुआ नहीं जाना चाहिए ...)।

समान रूप से, इंटीजर अपरिवर्तनीय है, क्योंकि इसे संशोधित करने का कोई तरीका नहीं है।

इससे कोई फर्क नहीं पड़ता कि आप इसे कैसे बनाते हैं।


new String() एक अभिव्यक्ति है जो एक String उत्पन्न करती है ... और एक String अपरिवर्तनीय है, इससे कोई फर्क नहीं पड़ता कि यह कैसे बनाया जाता है।

(यह पूछने पर कि क्या new String() परिवर्तनीय है या नहीं, यह गैरकानूनी है। यह प्रोग्राम कोड है, मूल्य नहीं। लेकिन मैं इसे लेता हूं कि यह वास्तव में आपके लिए नहीं था।)

अगर मैं एक स्ट्रिंग ऑब्जेक्ट String c = ""; रूप में बनाता हूं String c = ""; पूल में बनाई गई एक खाली प्रविष्टि है?

हाँ; यानी, खाली स्ट्रिंग के लिए एक प्रविष्टि बनाई गई है। खाली String बारे में कुछ खास नहीं है।

(Pedantic होने के लिए, "" कोड के लिए पूल प्रविष्टि आपके कोड को निष्पादित होने से बहुत पहले बनाया जाता है। असल में, यह तब बनाया जाता है जब आपका कोड लोड हो जाता है ... या संभवतः इससे पहले भी।)

तो, मैं जानना चाहता था कि नया ढेर ऑब्जेक्ट भी अपरिवर्तनीय है, ...

हाँ यही है। लेकिन अपरिवर्तनीयता स्ट्रिंग ऑब्जेक्ट्स की एक मौलिक संपत्ति है। सभी String ऑब्जेक्ट्स।

आप देखते हैं, String एपीआई बस String को बदलने के लिए कोई तरीका नहीं प्रदान करता है। तो (प्रतिबिंब का उपयोग करके कुछ खतरनाक और मूर्ख 1 चाल के अलावा), आप एक String म्यूटेट नहीं कर सकते हैं।

और यदि ऐसा है तो उद्देश्य क्या था?

जावा String को एक अपरिवर्तनीय वर्ग के रूप में डिज़ाइन किया गया कारण सादगी है। कोर स्ट्रिंग क्लास एक अपरिवर्तनीय इंटरफ़ेस प्रदान करता है, तो यह सही प्रोग्राम लिखना आसान बनाता है, और अन्य लोगों के कोड के बारे में पढ़ने / कारण बनाता है। (या कम से कम, यह डिजाइन डिजाइन के लिए तर्क है, जैसा कि मैं इसे समझता हूं।)

उत्तर से जाकर, मैं इकट्ठा करता हूं कि वही चर के अन्य संदर्भ एक कारण हैं। अगर मैं इसे समझने में सही हूं तो कृपया मुझे बताएं।

नहीं। यह उससे अधिक मौलिक है। बस, सभी String ऑब्जेक्ट्स अपरिवर्तनीय हैं। इसे समझने के लिए आवश्यक कोई जटिल विशेष मामला तर्क नहीं है। यह बस >> है <<।

रिकॉर्ड के लिए, यदि आप जावा में एक परिवर्तनीय "स्ट्रिंग-जैसी" ऑब्जेक्ट चाहते हैं, तो आप स्ट्रिंगबिल्डर या स्ट्रिंगबफर का उपयोग कर सकते हैं। लेकिन ये स्ट्रिंग के लिए अलग-अलग प्रकार हैं।

1 - इन चालें (आईएमओ) खतरनाक और मूर्ख हैं क्योंकि वे तारों के मूल्यों को प्रभावित करते हैं जिन्हें संभावित रूप से स्ट्रिंग पूल के माध्यम से आपके आवेदन के अन्य हिस्सों द्वारा साझा किया जाता है। इससे अराजकता हो सकती है ... इस तरीके से कि आपके कोड को बनाए रखने वाले अगले व्यक्ति को ट्रैक करने का थोड़ा मौका होता है।


वास्तव में, यह दूसरी तरफ है।

[...] String क्लास को डिज़ाइन किया गया है ताकि सामान्य पूल में मूल्यों को अन्य स्थानों / चरों में पुन: उपयोग किया जा सके।

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

तो, इस पर विचार करें:

// this string literal is interned and referenced by 'a'
String a = "Hello World!";

// creates a new instance by copying characters from 'a'
String b = new String(a);

अब, क्या होता है यदि आप बस अपने नव निर्मित b चर के संदर्भ का निर्माण करते हैं?

// 'c' now points to the same instance as 'b'
String c = b;

कल्पना करें कि आप एक अलग थ्रेड पर एक विधि के लिए c (या, विशेष रूप से, जिस वस्तु को संदर्भित कर रहे हैं) पास करते हैं, और अपने मुख्य धागे पर एक ही उदाहरण के साथ काम करना जारी रखें। और अब कल्पना करें कि क्या होगा यदि तार विचलित हो।

वैसे भी यह मामला क्यों है?

यदि कुछ और नहीं है, तो ऐसा इसलिए है क्योंकि अपरिवर्तनीय वस्तुएं मल्टीथ्रेडिंग को अधिक सरल बनाती हैं, और आमतौर पर तेज़ भी होती हैं। यदि आप अलग-अलग धागे के बीच एक म्यूटेबल ऑब्जेक्ट (जो कि किसी भी राज्यव्यापी वस्तु, उत्परिवर्ती निजी / सार्वजनिक क्षेत्रों या गुणों के साथ) साझा करते हैं, तो आपको सिंक्रनाइज़ पहुंच (म्यूटेक्स, सेमफोर) सुनिश्चित करने के लिए विशेष देखभाल करने की आवश्यकता होती है। इसके साथ ही, आपको अपने सभी परिचालनों में परमाणुता सुनिश्चित करने के लिए विशेष देखभाल की आवश्यकता है। मल्टीथ्रेडिंग मुश्किल है।

प्रदर्शन प्रभावों के बारे में, ध्यान दें कि पूरी तरह से एक सिंगल कैरेक्टर को बदलने के लिए पूरी स्ट्रिंग को एक नए इंस्टेंस में कॉपी करना वास्तव में थ्रेड-सुरक्षित पहुंच सुनिश्चित करने के लिए सिंक्रनाइज़ेशन संरचनाओं के कारण एक महंगा संदर्भ स्विच को प्रेरित करने से तेज़ है। और जैसा कि आपने उल्लेख किया है, अपरिवर्तनीयता भी आंतरिक संभावनाएं प्रदान करती है, जिसका अर्थ है कि यह वास्तव में स्मृति उपयोग को कम करने में मदद कर सकता है।

आम तौर पर जितना सामान आपके कर सकते हैं उतना सामान बनाने के लिए यह एक अच्छा विचार है।







immutability