2013-01-23 11 views
8

मैंने यह Questions about Java's String pool पढ़ा और स्ट्रिंग पूल की मूल अवधारणा को समझ लिया लेकिन फिर भी व्यवहार को समझ में नहीं आया।स्ट्रिंग पूल व्यवहार

पहले: यह काम करता है अगर आप सीधे s2 मान असाइन और दोनों S1 और पूल

String s1 = "a" + "bc"; 
String s2 = "ab" + "c"; 
System.out.println("s1 == s2? " + (s1 == s2)); 

लेकिन फिर अगर मैं बदल स्ट्रिंग S1 + = "डी", तो पूल में एक ही वस्तु को देखें एक स्ट्रिंग ऑब्जेक्ट "abcd" होना चाहिए? तो जब मैं s2 + = "d" बदलता हूं, तो उसे पूल में स्ट्रिंग ऑब्जेक्ट "abcd" मिलना चाहिए और ऑब्जेक्ट को s2 को असाइन करना चाहिए? लेकिन ऐसा नहीं है और वे एक ही वस्तु को संदर्भित नहीं हैं। ऐसा क्यों है?

String s1 = "abc"; 
String s2 = "abc"; 
System.out.println("s1 == s2? " + (s1 == s2)); 

s1 += "d";     
s2 += "d"; 
System.out.println("s1 == s2? " + (s1 == s2)); 
+0

[जावा के स्ट्रिंग पूल के बारे में प्रश्न] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/1881922/questions-about-javas-string-pool) – EJP

+0

@EJP Asker उस विषय का उल्लेख करता है और कहता है कि यह नहीं हुआ अपने सवालों का जवाब दें। – glomad

उत्तर

7

स्ट्रिंग्स जमा किया जाना है जब आप एक स्ट्रिंग पर String.intern() फोन की गारंटी है।

String s1 = "abcd".intern(); 
String s2 = "abc"; 
s2 += "d"; 
s2 = s2.intern(); 
s1 == s2 // returns true 

जब संकलक एक निरंतर यह, अनुकूलन और शाब्दिक स्ट्रिंग पूल करने के लिए यानी बहुत चालाक है देखता है:

String s1 = "abcd"; 
String s2 = "abcd"; 
s1 == s2 // returns true 

Java Language Specification कहता है:

प्रत्येक स्ट्रिंग शाब्दिक एक संदर्भ (§ है 4.3) कक्षा स्ट्रिंग (§4.3.3) के एक उदाहरण (§4.3.1, §12.5) पर। स्ट्रिंग ऑब्जेक्ट्स का निरंतर मूल्य होता है। स्ट्रिंग शाब्दिक-या अधिक सामान्य रूप से तार कि लगातार भाव (§15.28) के मूल्यों हैं -क्या तो के रूप में अद्वितीय उदाहरण हैं साझा करने के लिए "प्रशिक्षु", विधि String.intern का उपयोग कर।

तो s2 += "d" के मामले में, संकलक नहीं के रूप में चतुर के रूप में आप कर रहे हैं था और बस "d" जमा।

+2

जबकि यह उत्तर एक सच्चा तथ्य बताता है, यह प्रश्न के आधार पर * क्यों * समझाता नहीं है। – Vulcan

+0

दिलचस्प है, तो क्या पूरे स्ट्रिंग पूल चीज़ बिंदु को याद कर रही है? अगर मुझे प्रत्येक स्ट्रिंग में .intern() जोड़ने की ज़रूरत है? – Jaxox

+5

@ user2005443 आपको आम तौर पर प्रत्येक स्ट्रिंग में 'intern()' नहीं जोड़ना चाहिए। यह समयपूर्व अनुकूलन है। यदि कुछ स्ट्रिंग्स हैं जिन्हें आप जानते हैं (या प्रोफाइलिंग के माध्यम से पता लगाएं) का उपयोग बहुत अधिक किया जा रहा है, यह प्रदर्शन में सुधार करने में मदद कर सकता है, लेकिन यदि आप इसे अंधाधुंध तरीके से उपयोग करते हैं तो यह [काफी खतरनाक] हो सकता है (http: //www.codeinstructions। कॉम/2009/01/पर्दाफाश-javalangstringintern-myths.html)। – Jeff

0

यह मेरा अनुमान है:

स्ट्रिंग एस 1 = "एक" + "ई.पू."; स्ट्रिंग एस 2 = "एबी" + "सी";

मुझे लगता है कि संकलित समय ये एक ही स्ट्रिंग का उत्पादन करने के लिए निर्धारित हैं और इसलिए दोनों के लिए केवल एक वस्तु बनाई गई है।

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

+0

क्यों अनुमान लगाओ? यह सब जेएलएस में वर्णित है। – EJP

3

मुझे इस बारे में निश्चित नहीं है, इसलिए यह बहुत अधिक अटकलें है, लेकिन मुझे संदेह है कि पहले उदाहरण में कुछ कंपाइलर चाल चल रही है (जहां यह इनलाइन और स्पष्ट है कि क्या हो रहा है), लेकिन यह नहीं है दूसरे उदाहरण में इसे खींचने के लिए पर्याप्त चालाक (जहां यह इतना स्पष्ट नहीं है)।

अगर मैं सही हूँ, या तो संकलक "a" + "bc" देखता है और बस उस नीचे "abc" को संपीड़ित करता संकलन समय पर या यह दो पंक्तियों देखने और तार पूलिंग क्योंकि यह महसूस करता है कि उपयोग किया जाएगा है। मैं पूर्व पर सट्टेबाजी कर रहा हूं ..

सभी तारों को आवश्यक रूप से पूल नहीं किया जाता है।

+7

यह सही है, संकलक संकलन-समय स्थिरांक पर निरंतर फोल्डिंग करता है और कक्षा के निरंतर पूल में केवल एक स्ट्रिंग, "एबीसी" रखता है। मेरा मानना ​​है कि निरंतर पूल से आने वाले सभी तारों को प्रशिक्षित किया जाता है। रन टाइम पर बनाए गए अन्य तार, तब तक प्रशिक्षित नहीं होते हैं जब तक कि आप स्पष्ट रूप से उन पर स्ट्रिंग # इंटर्न को कॉल न करें। –

+0

वास्तव में ऐसा होता है। यदि आप बाइटकोड की जांच करते हैं, तो आप देखेंगे कि "ए" + "बीसी" का अनुवाद एक एलडीसी निर्देश (निरंतर धक्का) में किया जाता है, जबकि अन्य निर्देश s1 + "d" स्ट्रिंगबिल्डर को कॉल करने के लिए अनुवाद करता है। – Gothmog

2

String#intern() के लिए प्रलेखन देखें। अंतिम पंक्ति वहाँ राज्यों:

सभी शाब्दिक तार और स्ट्रिंग मूल्य स्थिर भाव प्रशिक्षु हैं। तो यह स्ट्रिंग पूल में डाल नहीं है

आपका += उदाहरण है, न तो एक शाब्दिक स्ट्रिंग है और न ही एक स्ट्रिंग-मान निरंतर अभिव्यक्ति है।

2

संकलक निरंतर मूल्यांकन प्रदर्शन कर सकते हैं, लेकिन इस मामले में नहीं आप मूल्यों

संशोधित जहां बजाय निम्न प्रयास करें और देखें अगर आप या तो चर से final ड्रॉप क्या होता है।

final String s1 = "abc"; 
final String s2 = "abc"; 
System.out.println("s1 == s2? " + (s1 == s2)); 

String s3 = s1 + "d";     
String s4 = s2 + "d"; 
System.out.println("s3 == s4? " + (s3 == s4)); 
0

मुझे लगता है कि यहाँ क्या होता है: 1. स्ट्रिंग एस 1 के लिए = "एक" + "ई.पू."; स्ट्रिंग एस 2 = "एबी" + "सी"; जावा कम्पाइलर बहुत चालाक पता चला है कि एस 1 के वस्तुतः मान और s2 ही कर रहे हैं, इसलिए संकलक स्ट्रिंग पूल

    S1 + = "डी" के लिए
  1. में एक ही शाब्दिक मूल्य के लिए उन्हें बताते हैं;
    एस 2 + = "डी";

कोई रास्ता नहीं संकलक जानते हैं कि एस 1 और एस 2 एक ही मूल्य, रनटाइम पर किया जा रहा हो जाएंगे होती है, जब तक आप String.intern() कहते हैं, JVM देखने के लिए शाब्दिक पूल स्ट्रिंग की जांच नहीं करेगा मूल्य पहले से ही है।

संबंधित मुद्दे