2016-07-15 5 views
19

मैं अगर तुमJVM पुन: उपयोग स्ट्रिंग सबस्ट्रिंग्स को कैसे पुन: उपयोग करता है?

for (condition) { 
    String s = "hi there"; 
} 

बस एक String उदाहरण सभी पुनरावृत्तियों में बन जाता है बनाने के लिए, String s = new String("hi there"); विपरीत प्रत्येक चरण में एक नया उदाहरण पैदा करेगा कि बारे में पता कर रहा हूँ।

लेकिन, यहोशू बलोच से पढ़ने प्रभावी जावा: अध्याय 2 आइटम 5 (पेज 20) यह कहता है:

इसके अलावा, यह गारंटी है कि वस्तु ही में चल रहे किसी अन्य कोड से पुन: उपयोग किया जाएगा वर्चुअल मशीन जो पर होती है समान स्ट्रिंग शाब्दिक [JLS, 3.10.5] होती है।

AFAIK नहीं कहा गया है कि के लिए होता एक ही स्ट्रिंग शाब्दिक हो, यह कहता है शामिल हैं।

पढ़ना [JLS, 3.10.5] इस पर कोई सटीक संदर्भ नहीं मिल रहा है और मुझे संदेह है।

String s1 = "hi "; 
String s2 = "there"; 
String s3 = "hi there"; 

कैसे कई मामलों बनाई गई हैं:

इस स्निपेट देते?

  • 3 उदाहरण (इस प्रकार, वाक्यांश वास्तव में सटीक नहीं है)।
  • 2 उदाहरणों, s1 और s2
+1

शायद इसका अर्थ है "वर्चुअल मशीन में ..", स्ट्रिंग में कोई अन्य स्ट्रिंग –

+1

नहीं है, मुझे यकीन नहीं है, इसलिए उत्तर के बजाय एक टिप्पणी। लेकिन मुझे लगता है कि "युक्त" आंशिक रूप से गलत है और आपका उदाहरण वास्तव में तीन उदाहरण उत्पन्न करता है। – glglgl

+0

@glglgl वास्तव में क्या है * मेरा तर्क * कहता है, लेकिन 's1' + s2' के संदर्भ के रूप में 's3' बनाने के लिए पर्याप्त JVM स्मार्ट हो सकता है ?? –

उत्तर

17

JLS जो भी उप-तार के किसी भी पुन: उपयोग की गारंटी नहीं है (तब s3s1 और s2 संदर्भ पुन: उपयोग के लिए बनाया जाता है)। यहां "कंटेन" का मतलब है कि वर्ग सटीक वही स्ट्रिंग को कहीं भी वर्णित करता है। यह "सबस्टिंग" अर्थ में उपयोग किया जाता है।

+2

विशेष रूप से _ "कोई अन्य कोड [..] जिसमें ** समान स्ट्रिंग अक्षर ** ** _ (जोर मेरा) –

+1

होता है जब आप कहते हैं * सब-स्ट्रिंग्स के किसी भी पुन: उपयोग की गारंटी नहीं है * इसका मतलब है कि कभी-कभी ऐसा हो सकता है? –

+3

@ जोर्डी कैस्टिला: मुझे नहीं लगता कि कोई भी मौजूदा वीएम सबस्ट्रिंग का पुन: उपयोग करता है, लेकिन यह संभव है (और ओपनजेडीके के पिछले पुनरावृत्तियों उदाहरण के लिए कभी-कभी अंतर्निहित char [] साझा करते थे जब दो तार एक-दूसरे के सबस्ट्रिंग होते थे)। ध्यान दें कि आप * अभी भी अलग-अलग 'स्ट्रिंग' उदाहरणों का निरीक्षण करेंगे और यह पता लगाने के लिए कोई सार्वजनिक एपीआई नहीं है कि यह हो रहा है (यानी आप कुछ प्रतिबिंबित चाल के बिना बताने में सक्षम नहीं होंगे)। –

3

प्रत्येक कक्षा फ़ाइल में उस वर्ग के भीतर उपयोग किए जाने वाले सभी स्ट्रिंग अक्षर या अन्य स्थिरांक की एक सूची होती है (निर्देश संख्या में एम्बेडेड छोटे संख्यात्मक स्थिरांक को छोड़कर)। यदि सूची में आइटम 1 स्ट्रिंग अक्षर "Freddy" है, और स्थानीय चर Fred में 6 की अनुक्रमणिका है, तो Fred="Freddy"; के लिए जेनरेट किया गया बाइटकोड ldc 19/astore 6 होगा।

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

क्या महत्वपूर्ण है कि समय एक वर्ग रन, वस्तुओं सभी स्ट्रिंग शाब्दिक उसमें लिए बनाया गया है में कोड के किसी भी द्वारा, इसलिए Fred="Freddy"; की तरह एक बयान महज एक संदर्भ पहले से मौजूदा StringFreddy युक्त वस्तु के लिए की दुकान जाएगा , एक नया String ऑब्जेक्ट बनाने के बजाय।

2

तो s3 पुन: उपयोग किया s1 और s2 उदाहरणों, तो s3 शारीरिक रूप से एक सतत चरित्र सरणी के रूप में प्रतिनिधित्व होगा नहीं किया जा, बल्कि String रों वस्तुओं की एक समग्र String होगा।

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

वास्तव में, विपरीत भावना कर सकता है: केवल एक अंतर्निहित चार अनुक्रम "hi there" (s3), और s1 और s2 के लिए आवंटित किया जा सकता है सिर्फ अपने लंबाई और कि स्ट्रिंग के भीतर पहले वर्ण के पते संग्रहीत कर सकती है। लेकिन मुझे लगता है कि यह 'एम्बेड करने योग्य' उम्मीदवारों की पहचान करने के लिए जेवीएम के लिए एक जटिल और महंगा काम होगा और लागत संभावित लाभ से अधिक होगी।

+1

ठीक है, जावा 7 से पहले 'सबस्ट्रिंग' विधि को इस तरह कार्यान्वित किया जाता था कि उसने मूल स्ट्रिंग के चरित्र सरणी द्वारा समर्थित स्ट्रिंग को वापस कर दिया, लेकिन यह भी गिरा दिया गया क्योंकि इससे अच्छे से अधिक नुकसान हुआ (बड़े ग्रंथ उदाहरण के लिए, कुछ छोटे सबस्ट्रिंग का संदर्भ रखकर जीवित रखा गया है) – Hulk

+1

@ हल्क: यह [जावा 7update6 में बदल गया है] (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4513622)। यह केवल एक जीसी मुद्दा नहीं है; इसके लिए प्रत्येक स्ट्रिंग को 'ऑफसेट' और 'लम्बाई' क्षेत्र को एक ही ऑपरेशन, 'substring' के एकमात्र उद्देश्य के लिए ले जाना आवश्यक है। इसके अलावा, हालिया जेवीएम की स्ट्रिंग deduplication सुविधा सरलीकृत ऑब्जेक्ट लेआउट से 'मूल्य' फ़ील्ड पर एकल 'cas' के रूप में लाभ पर्याप्त है। – Holger

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