2012-10-14 20 views
7

JLS (15.28 लगातार भाव) केवल युक्त अभिव्यक्ति के अनुसार:रनटाइम स्ट्रिंग संयोजन मूल्यांकन

i)Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, 
§3.10.4, §3.10.5) 
or 
ii)Simple names (§6.5.6.1) that refer to constant variables (§4.12.4). 
or 
iii)... 

एक निरंतर अभिव्यक्ति है।

अब String s1="a"+"b"; एक निरंतर अभिव्यक्ति है और संकलन समय पर "ab" पर मूल्यांकन किया जाएगा।

तो s1="ab";

[1] क्या मैं सही हूँ कह रही है कि अब वहाँ स्ट्रिंग पूल में तीन वस्तुओं ऊपर बयान के अनुसार के रूप में कर रहे हैं में: -, "एक", "बी" "ab" ???

अब,

final String s="a"; 
final String s1="b"; 
String s2=s+s1; // is also constant expression and get evaluated at compile time. 

ऊपर कोड संकलन के बाद s2="a"+"b"; को transaled कर दिया जाएगा।

तो s2="ab"; स्वचालित रूप से स्ट्रिंग पूल में संग्रहीत किया जाएगा।

लेकिन,

// note there is no final now. 
String s="a"; 
String s1="b"; 
String s2="a"+"b"; // constant expression. 
String s3=s+s1; // is NOT a constant expression and get evaluated at RUN TIME. 
String s3=s+s1; के लिए

, कोड के लिए अनुवाद किया जाएगा:

s3=new StringBuilder(String.valueOf(s)).append(s1).toString(); 

और एक नया स्ट्रिंग वस्तु का निर्माण करेगा।

इसलिए, s2==s3 झूठी होने के लिए बाहर आ जाएगा;

क्या इसका मतलब है स्ट्रिंगबिल्डर का उपयोग कर रनटाइम पर मूल्यांकन स्ट्रिंग कॉन्सटेनेशन का परिणाम स्ट्रिंग पूल में संग्रहीत नहीं होता है बल्कि इसके बजाय हीप (पूल के बाहर) में जाता है?

+1

ध्यान दें कि संकलन चरण के दौरान स्ट्रिंग पूल स्ट्रिंग पूल के समान नहीं है जब आपका प्रोग्राम चलाया जाता है। –

+0

@ Thorbjørn Ravn Andersen: अच्छा बिंदु। क्या आप मुझे कोई लिंक या स्रोत दे सकते हैं जहां मैं आपके बिंदु का विवरण देख सकता हूं। –

उत्तर

3

JLS §15.18.1 से:

15.18.1। स्ट्रिंग जोड़ना ऑपरेटर +

केवल एक संकार्य अभिव्यक्ति प्रकार स्ट्रिंग की है, तो स्ट्रिंग रूपांतरण (§5.1.11) रन-टाइम में एक स्ट्रिंग उत्पादन के लिए अन्य संकार्य पर किया जाता है।

स्ट्रिंग कॉन्सटेनेशन का परिणाम स्ट्रिंग ऑब्जेक्ट का संदर्भ है जो दो ऑपरेंड स्ट्रिंग्स का संयोजन है। बाएं हाथ के ऑपरेंड के वर्णित नव निर्मित स्ट्रिंग में दाईं ओर ऑपरेंड के पात्रों से पहले हैं।

स्ट्रिंग ऑब्जेक्ट नव निर्मित (§12.5) है जब तक कि अभिव्यक्ति संकलन-समय निरंतर अभिव्यक्ति (§15.28) न हो।

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

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

तो,

  1. वहाँ लगातार पूल ("ab") में एक वस्तु है। अस्थायी नहीं बचाए जाते हैं।
  2. इसी प्रकार, निरंतर पूल में केवल "ab" होगा।
  3. नई स्ट्रिंग एक नई String ऑब्जेक्ट है और स्पष्ट रूप से प्रशिक्षित होने तक पूल में नहीं होगी।

यह कुछ बाईटकोड को देखने के लिए शिक्षाप्रद है:

String sa1 = "a"+ "b"; 

final String sb1 = "a"; 
final String sb2 = "b"; 
String sb3 = sb1 + sb2; 

String sc1 = "a"; 
String sc2 = "b"; 
String sc3 = "a" + "b"; 
String sc4 = sc1 + sc2; 

हो जाता है

Code: 
    0: ldC#2; //String ab 
    2: astore_0 
    3: ldC#2; //String ab 
    5: astore_3 
    6: ldC#3; //String a 
    8: astore 4 
    10: ldC#4; //String b 
    12: astore 5 
    14: ldC#2; //String ab 
    16: astore 6 
    18: new #5; //class java/lang/StringBuilder 
    21: dup 
    22: invokespecial #6; //Method java/lang/StringBuilder."<init>":()V 
    25: aload 4 
    27: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    30: aload 5 
    32: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    35: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    38: astore 7 
    40: return 

आप देख सकते हैं कि पहले दो मामलों में, "ab" सीधे निरंतर पूल से भरी हुई है । तीसरे ब्लॉक में, हमें sc4 = new StringBuilder().append(sc1).append(sc2).toString() अनुवाद मिलता है, जो एक नई वस्तु बनाता है।

0

कि स्ट्रिंग संयोजन का परिणाम मतलब क्रम पर मूल्यांकन किया जाता है स्ट्रिंग पूल में संग्रहीत नहीं StringBuilder का उपयोग कर, लेकिन ढेर (पूल के बाहर) में बजाय चला जाता है

हां। वह सही है। यह ढेर में नई वस्तु पैदा करेगा।

1

क्या मैं कह रहा हूं कि अब उपरोक्त कथन के अनुसार स्ट्रिंग पूल में तीन वस्तुएं हैं: - "ए", "बी", "अब" ???

नहीं। आप गलत हैं। संकलन समय संकलन पर किया जाता है, और केवल "ab" ऑब्जेक्ट स्ट्रिंग पूल में संग्रहीत किया जाएगा।

क्या इसका मतलब है स्ट्रिंगबिल्डर का उपयोग कर रनटाइम पर मूल्यांकन स्ट्रिंग कॉन्सटेनेशन का परिणाम स्ट्रिंग पूल में संग्रहीत नहीं होता है बल्कि इसके बजाय हीप (पूल के बाहर) में जाता है?

हां, आप इस बिंदु पर सही हैं।


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

किसी भी तरह से, आपको तारों की तुलना करने के लिए == का उपयोग करने से बचना चाहिए।

+0

+1 1 कथन – Ankur

+0

के लिए +1 मैं सुझाव देता हूं कि केवल 'String.intern()' को कॉल करने के बारे में एक नोट जोड़ने का सुझाव दें यदि कोई विशेषज्ञ कहता है कि यह एक अच्छा विचार है। –

0

हां, आप सही हैं कि स्ट्रिंगबिल्डर का उपयोग करके रनटाइम पर स्ट्रिंग का मूल्यांकन स्ट्रिंग पूल में संग्रहीत नहीं होता है। क्योंकि:

AbstractStringBuilder (पूर्णांक क्षमता) { मूल्य:

  1. एक new ऑपरेटर (जो ढेर में वस्तु के लिए नए स्मृति आवंटित करती है)
  2. नहीं है और हम कोड के रूप में देख सकते हैं = नया चार [क्षमता]; }

वहाँ एक नया चार सरणी संदर्भ ढेर में आवंटित है।

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