2012-03-14 12 views
52

स्ट्रिंग की तुलना करने के लिए मेरे पास कोड की निम्नलिखित पंक्तियां हैं। str1 str2 के बराबर नहीं है, जो समझ में आता है क्योंकि यह ऑब्जेक्ट संदर्भ की तुलना करता है। लेकिन फिर एस 1 एस 2 के बराबर क्यों है?संदर्भ तुलना (==) जावा में कुछ तारों के लिए क्या काम करता है?

String s1 = "abc"; 
String s2 = "abc"; 

String str1 = new String("abc"); 
String str2 = new String("abc"); 

if (s1==s2) 
    System.out.println("s1==s2");   
else 
    System.out.println("s1!=s2"); 

if (str1==str2) 
    System.out.println("str1==str2");   
else 
    System.out.println("str1!=str2"); 

if (s1==str1) 
    System.out.println("str1==s1");   
else 
    System.out.println("str1!=s1"); 

आउटपुट:

s1==s2 
    str1!=str2 
    str1!=s1 
+12

तो आपके द्वारा पहली खोज की कोशिश की? :( –

+13

http://stackoverflow.com/questions/7144059/java-string-pool-object-creation, http://stackoverflow.com/questions/4033625/if-compares-references-in-java-why-does इन-स्ट्रिन के साथ-मूल्यांकन-से-सत्य, http://stackoverflow.com/questions/6377058/string-reference, http://stackoverflow.com/questions/1903094/java-strings-and-stringpool –

+1

(मैं इसे बंद नहीं कर रहा हूं, क्योंकि मुझे एक और प्रश्न * इस तरह केंद्रित नहीं है * लेकिन मुझे यकीन है कि यह मौजूद है) –

उत्तर

80

स्ट्रिंग निरंतर पूल अनिवार्य रूप से सभी स्ट्रिंग शाब्दिक कैश ताकि वे एक ही वस्तु के नीचे रहे हैं, जिसके कारण आप उत्पादन आप s1==s2 लिए क्या देखेंगे। जब भी एक शाब्दिक घोषित किया जाता है, तो यह एक नई स्ट्रिंग ऑब्जेक्ट बनाने से बचने के लिए अनिवार्य रूप से वीएम में एक अनुकूलन है, जो बहुत महंगा हो सकता है! अपने str1==str2 उदाहरण के साथ, आप नई स्ट्रिंग ऑब्जेक्ट्स बनाने के लिए स्पष्ट रूप से वीएम को बता रहे हैं, इसलिए यह गलत क्यों है।

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

+2

आपने मुझे इंटर्न() विधि विचार देने के लिए केवल 2 सेकंड को हराया। –

+6

आप खो देते हैं आपको स्नूज़ करें। हाहा जे/के। = पी –

+1

+1 लेकिन यह भी ध्यान देने योग्य है कि सामान्य पूल में स्ट्रिंग्स को सामान्य रूप से जोड़ना एक बुरा विचार है क्योंकि इससे मेमोरी लीक को मुश्किल से पता चल सकता है। केवल स्ट्रिंग्स के एक छोटे से नंबर के लिए ऐसा करें जो वास्तव में स्थिरांक (जैसे हैश मैप कुंजी) के रूप में उपयोग किया जा रहा है, मनमाने ढंग से स्ट्रिंग डेटा के लिए कभी नहीं। – mikera

18

एस 1 और एस 2 स्ट्रिंग अक्षर हैं। जब आप एक नया स्ट्रिंग अक्षर बनाते हैं तो संकलक पहले जांचता है कि क्या इसका प्रतिनिधित्व करने वाला कोई भी शाब्दिक स्ट्रिंग पूल में मौजूद है या नहीं। यदि कोई उपस्थित है, तो संकलक उस शाब्दिक रूप से लौटाता है अन्यथा संकलक एक नया बनाता है।

जब आपने स्ट्रिंग s2 बनाया था तो संकलक पूल से स्ट्रिंग s1 लौटाता है क्योंकि यह पहले से ही बनाया गया था। यही कारण है कि s1 और s2 समान हैं। इस व्यवहार को इंटर्निंग कहा जाता है।

+0

जब आप कहते हैं कि "कंपाइलर एक नया बनाता है" तो मैं थोड़ा उलझन में हूं। AFAIK, कंपाइलर मध्यवर्ती मशीन कोड बनाने के लिए है और वास्तव में स्मृति में किसी ऑब्जेक्ट को चलाता है (इसलिए बनाता है)। क्या आपका मतलब है कि कंपाइलर _replaces_ स्ट्रिंग अक्षर? कृपया इसे स्पष्ट करें। – peakit

+0

मेरे पास अभी कोई सहायक दस्तावेज नहीं है, लेकिन मेरा मानना ​​है कि @ कंधरा शेखर जेआईटी या जस्ट इन टाइम कंपाइलर का जिक्र कर रहा था, न कि जावैक कंपाइलर। – Robert

3

जावा में, एक ही स्थिर स्ट्रिंग का पुन: उपयोग किया जाएगा। ताकि s1 और s2 उसी "एबीसी" ऑब्जेक्ट और s1==s2 पर इंगित करें। लेकिन जब आप new String("abc") का उपयोग करते हैं, तो एक और ऑब्जेक्ट बनाया जाएगा। तो s1 != str1

5

यह स्ट्रिंग अक्षरों को प्रशिक्षित करने के कारण है। इस मामले पर, Java documentations का कहना है:

सभी शाब्दिक तार और स्ट्रिंग मूल्य स्थिर भाव प्रशिक्षु

हैं और यह बताता है कि क्यों s1 और s2 ही (इन दोनों चर एक ही प्रशिक्षु को इंगित कर रहे हैं स्ट्रिंग)

9

यह घटना String interning के कारण है।

असल में, सभी स्ट्रिंग अक्षर "कैश" और पुन: उपयोग किए जाते हैं।

0

string के रूप में जावा में अपरिवर्तनीय है, सभी string literals पुनर्प्रयोग के लिए कैश की गई।

जब आप नए() ऑपरेटर का उपयोग करके स्ट्रिंग ऑब्जेक्ट बनाते हैं, तो यह हमेशा हीप मेमोरी में एक नई वस्तु बनाते हैं। दूसरी ओर, यदि आप स्ट्रिंग शाब्दिक वाक्यविन्यास का उपयोग कर ऑब्जेक्ट बनाते हैं उदा।"जावा", यह स्ट्रिंग पूल से मौजूदा ऑब्जेक्ट लौटा सकता है (पर्म जेन स्पेस में स्ट्रिंग ऑब्जेक्ट का कैश, जिसे अब हाल ही में जावा रिलीज में हीप स्पेस में ले जाया गया है), यदि यह पहले से मौजूद है। अन्यथा यह एक नई स्ट्रिंग ऑब्जेक्ट बनाएगा और भविष्य में पुन: उपयोग के लिए स्ट्रिंग पूल में रखेगा।

String s1 = new String("java"); 
String s2 = new String("java"); 
String s3 = "java"; 
String s4 = "java"; 

enter image description here

Please refer this link

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