दिलचस्प पोस्ट
जावास्क्रिप्ट / JQuery: $ (विंडो)। पुनः आकार के पूरा होने के बाद कैसे आग लगाएगा? लिनक्स पर बॉड दर को 307200 तक कैसे सेट करना है? asio async_write को बढ़ावा दें: कैसे async_write कॉल interleaving नहीं? "स्थानीय" डाटा के साथ jqGrid उपग्रिड मुख्य () के लिए तर्क क्या हैं? मैं अपने आप को एक पावर फंक्शन कैसे लिख सकता हूं? हर व्यक्ति का उपयोग न किए गए नाम स्थान की घोषणाओं (यानी std :: not :: std: :) क्यों है? अंतिम और अंतिमऑर्ड डीफॉल्ट समर्थित नहीं है उरी से अलग-अलग क्वेरी पैरामीटर प्राप्त करें जीआईटी में प्रॉक्सी के पीछे एसएसएच के माध्यम से गोटो में हीक्यू मास्टर को घुमाइए डेटाबेस कब और क्यों महंगे हो? गतिशील रूप से एक गुमनाम प्रकार का निर्माण करना? सूची <DerivedClass> की सूची <BaseClass> परिवर्तित करें कैसे अजगर में कंसोल विंडो छिपाना? सीरियलाइज़ और बूस्ट का उपयोग कर डेटा संरचना भेजें?

इंटर्न () जावा 6 और जावा 7 में अलग ढंग से व्यवहार कर रहा है

class Test { public static void main(String...args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1.intern()); String s2 = "Goodmorning"; if (s1 == s2) { System.out.println("both are equal"); } } } 

यह कोड जावा 6 और जावा 7 में विभिन्न आउटपुट उत्पन्न करता है। जावा 6 में s1==s2 2 की स्थिति false देता false और जावा 7 में s1==s2 2 true देता true । क्यूं कर?

यह प्रोग्राम जावा 6 और जावा 7 में अलग-अलग उत्पादन क्यों करता है?

Solutions Collecting From Web of "इंटर्न () जावा 6 और जावा 7 में अलग ढंग से व्यवहार कर रहा है"

ऐसा लगता है कि पहले की तरह एक अलग तरह से जेडीके 7 प्रक्रिया इंटर्न
मैंने इसे 1.7.0-बी 147 के निर्माण के साथ परीक्षण किया और "दोनों बराबर" हैं, लेकिन इसे 1 9.0_24 के साथ (उसी बाइटकोड) निष्पादित करते हुए मुझे संदेश नहीं मिला।
यह भी निर्भर करता है कि String b2 =... पंक्ति स्रोत कोड में स्थित है। निम्नलिखित कोड भी संदेश को आउटपुट नहीं करता है:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; String s2 = "Goodmorning"; System.out.println(s1.intern()); //just changed here s1.intern() and the if condition runs true if(s1 == s2) { System.out.println("both are equal"); } //now it works. } } 

ऐसा लगता है कि स्ट्रिंग को तारों के पूल में नहीं ढूंढने के बाद intern तरह, पूल में वास्तविक उदाहरण एस 1 को सम्मिलित करता है जब एस 2 बनाया गया है तो जेवीएम उस पूल का उपयोग कर रहा है, इसलिए इसे एस 1 बैक के रूप में एक ही संदर्भ मिलता है। दूसरी तरफ, यदि पहले 2 बना दिया गया है, तो यह संदर्भ पूल में जमा हो जाएगा।
यह जावा ढेर के स्थायी पीढ़ी से इंटर्नर्ड स्ट्रिंग्स को स्थानांतरित करने का एक परिणाम हो सकता है।

यहां मिले: महत्वपूर्ण आरएफई जेडीके 7 में संबोधित

जेडीके 7 में, अंतराल तार अब जावा ढेर के स्थायी पीढ़ी में आवंटित नहीं किए जाते हैं, लेकिन इसके बजाय जावा ढेर के मुख्य भाग (जिसे युवा और पुरानी पीढ़ियों के रूप में जाना जाता है) में आवंटित किया जाता है, साथ ही आवेदन द्वारा बनाए गए अन्य वस्तुओं के साथ । इस परिवर्तन के परिणामस्वरूप मुख्य जावा ढेर में रहने वाले अधिक डेटा और स्थायी जनरेशन में कम आंकड़े होंगे, और इस प्रकार समायोजित करने के लिए ढेर के आकार की आवश्यकता हो सकती है। इस परिवर्तन के कारण अधिकांश अनुप्रयोगों में हेप उपयोग में केवल अपेक्षाकृत छोटे अंतर दिखाई देंगे, लेकिन बड़े अनुप्रयोग जो कई वर्गों को लोड करते हैं या String.intern () विधि का भारी उपयोग करते हैं, वे अधिक महत्वपूर्ण अंतर देखेंगे

यकीन नहीं है कि यह एक बग है और किस संस्करण से … जेएलएस 3.10.5 राज्यों

किसी कंप्यूट की गई स्ट्रिंग को स्पष्ट रूप से इंटर्निंग करने का नतीजा एक ही स्ट्रिंग है, जैसा कि एक ही सामग्री वाली किसी पूर्व-मौजूद शाब्दिक स्ट्रिंग है।

तो सवाल यह है कि पूर्व-मौजूदा व्याख्या, संकलन-समय या निष्पादन-समय: "गुड मॉर्निंग" पूर्व-मौजूद है या नहीं?
मैं जिस तरह से इसे 7 से पहले कार्यान्वित किया गया था पसंद करता हूँ …

आइए उदाहरण से अनावश्यक विवरण छोड़ें:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints true for jdk7, false - for jdk6. } } 

चलो मान लें String#intern एक ब्लैक बॉक्स के रूप में String#intern कुछ परीक्षण मामलों चलाने के आधार पर, मैं निष्कर्ष निकालना होगा कि कार्यान्वयन निम्नलिखित है:

जावा 6:
अगर पूल में ऑब्जेक्ट के बराबर है, तो उस ऑब्जेक्ट के संदर्भ में लौटें, फिर नई स्ट्रिंग ( this बराबर) बनाएं, पूल में डालें, और बनाई गई उदाहरण के संदर्भ में लौटें।

जावा 7:
अगर पूल में ऑब्जेक्ट के बराबर है, तो उस ऑब्जेक्ट के संदर्भ में लौटें, और इसे पूल में डाल दें, और इसे वापस this

न तो जावा 6 और नवा 7 विधि के अनुबंध को तोड़ता है।

ऐसा लगता है कि नए इंटर्न विधि व्यवहार इस बग के ठीक होने का परिणाम था: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6962931

== संदर्भ की तुलना करता है प्रशिक्षु पद्धति यह सुनिश्चित करता है कि समान मूल्य के साथ तार समान संदर्भ हैं।

String.intern विधि के लिए javadoc बताते हैं:

सार्वजनिक स्ट्रिंग इन्टर ()

स्ट्रिंग ऑब्जेक्ट के लिए एक प्रामाणिक प्रतिनिधित्व देता है।

स्ट्रिंग का एक पूल, प्रारंभ में खाली, वर्ग स्ट्रिंग द्वारा निजी तौर पर बनाए रखा जाता है।

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

यह निम्नानुसार है कि किसी भी दो तारों के लिए और टी, s.intern () == t.intern () सच है अगर और केवल अगर s.equals (टी) सच है।

सभी शाब्दिक स्ट्रिंग्स और स्ट्रिंग-मूल्यवान निरंतर अभिव्यक्तियां interned हैं। स्ट्रिंग लीटरल्स को जावा भाषा विशिष्टता के §3.10.5 में परिभाषित किया गया है

रिटर्न: एक स्ट्रिंग जिसमें इस स्ट्रिंग के समान सामग्री है, लेकिन अद्वितीय स्ट्रिंग के पूल से होने की गारंटी है

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

Jdk6 में: String s1="Good"; लगातार पूल में एक स्ट्रिंग वस्तु "अच्छा" बनाता है

s1=s1+"morning"; लगातार पूल में एक और स्ट्रिंग ऑब्जेक्ट "सुबह" बनाता है, लेकिन इस समय वास्तव में जेवीएम करते हैं: s1=new StringBuffer().append(s1).append("morning").toString(); स्ट्रिंगबफ़र s1=new StringBuffer().append(s1).append("morning").toString();

अब जब new ऑपरेटर ढेर में एक ऑब्जेक्ट बनाता है, इसलिए s1 में संदर्भ ढेर निरंतर पूल नहीं है और String s2="Goodmorning"; निरंतर पूल में एक स्ट्रिंग ऑब्जेक्ट "गुड मॉर्निंग" बनाता है जिसका संदर्भ s2 में संग्रहीत है।

इसलिए, if(s1==s2) स्थिति झूठी है।

लेकिन जेडीके 7 में क्या होता है?

पहला मामला:

पहले कोड में आप स्नैप के पूल में वास्तव में तीन स्ट्रिंग जोड़ रहे हैं। 1. s1 = "अच्छा"
2. s1 = "गुड मॉर्निंग" (सम्मिलित करने के बाद) 3. s2 = "गुड मॉरीनिंग"

जबकि (s1 == s2) करते समय, वस्तुओं एक जैसे हैं, लेकिन अलग संदर्भ के रूप में यह गलत है।

दूसरा मामला:

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

  1. s1 = "अच्छा"
  2. s1 = "गुड मॉर्निंग" (समाप्ति के बाद)
  3. स्ट्रिंग s2 = "गुड मॉर्निंग" के लिए, नया स्ट्रिंग पूल में नहीं जोड़ा गया है और आपको मौजूदा 2 के लिए S2 के लिए संदर्भ मिलता है। इसलिए यदि (s1 == s2) सच देता है

आपको s1.equals(s2) का उपयोग करने की आवश्यकता है String ऑब्जेक्ट्स के साथ == का इस्तेमाल करना ऑब्जेक्ट रिफरेंस की तुलना खुद करता है।

संपादित करें: जब मैं अपना दूसरा कोड स्निपेट चलाता हूं, तो मुझे "दोनों बराबर" नहीं छूटे हैं I

संपादित करें 2: स्पष्ट किया गया है कि जब आप '==' का उपयोग करते हैं तो संदर्भों की तुलना की जाती है

स्ट्रिंग की तुलना करने के मुख्य रूप से 4 तरीके हैं:

  1. "== ऑपरेटर": यह सिर्फ स्ट्रिंग ऑब्जेक्ट के संदर्भ चर की तुलना करता है। इसलिए यह आपको अप्रत्याशित परिणाम दे सकता है, इस आधार पर कि आपने स्ट्रिंग या स्ट्रिंग क्लास के कन्स्ट्रक्टर का इस्तेमाल करते हुए या बस डबल कोट का उपयोग करके दोनों को अलग-अलग मेमोरी मिलती है (क्रमशः ढेर और पूल में)।
  2. "बराबर (ऑब्जेक्ट) विधि": यह ऑब्जेक्ट क्लास का तरीका है और स्ट्रिंग क्लास द्वारा ओवरलोड किया गया है। यह पूरी स्ट्रिंग की तुलना करती है और आईएसएएन सेंसिटिव है।
  3. "बराबर अनदेखा कैस (स्ट्रिंग) विधि": यह स्ट्रिंग क्लास की विधि है और पूरे स्ट्रिंग की तुलना करती है और संवेदनशील नहीं है I
  4. "स्ट्रिंग विधि की तुलना करें": चरित्र के आधार पर दोनों स्ट्रिंग वर्ण की तुलना करें और यदि उनका लौटा हुआ मूल्य 0 है, तो इसका अंतर वापसी करें, इसका मतलब है कि स्ट्रिंग समान हैं।

जब भी आप दो स्ट्रिंग के बीच तुलना कर रहे हैं, तो == का उपयोग न करें और eqauls() उपयोग eqauls() क्योंकि आप ऑब्जेक्ट्स की तुलना नहीं कर रहे हैं संदर्भ:

 string1.equals(string2); 

नतीजे कोड आश्रितों को रनटाइम:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints true for jdk7, false - for jdk6. } } 

यदि आप इस प्रकार लिखते हैं:

 class Test { public static void main(String... args) { String s = "GoodMorning"; String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints false for both jdk7 and jdk6. } } 

कारण 'एलडीसी # एन' (लगातार पूल से लोड स्ट्रिंग) और स्ट्रिंगइंडरी () दोनों हॉटस्पॉट जेवीएम में स्ट्रिंगटेबल का उपयोग करेंगे। विस्तार के लिए मैंने एक पूल अंग्रेजी लेख लिखा है: http://aprilsoft.cn/blog/post/307.html