JLS
JLS 7 3.10.5 इसे परिभाषित करता है और एक व्यावहारिक उदाहरण देता है:
इसके अलावा, एक स्ट्रिंग शाब्दिक हमेशा कक्षा स्ट्रिंग के एक ही उदाहरण को संदर्भित करता है। ऐसा इसलिए है क्योंकि स्ट्रिंग शाब्दिक - या, अधिक सामान्यतः, स्ट्रिंग्स जो निरंतर अभिव्यक्तियों (.215.28) के मान हैं - "इंटर्नड" हैं ताकि अद्वितीय उदाहरणों को साझा करें, विधि String.intern का उपयोग करके।
उदाहरण 3.10.5-1। स्ट्रिंग साहित्य
संकलन इकाई (consisting7.3) से मिलकर कार्यक्रम:
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
और संकलन इकाई:
package other;
public class Other { public static String hello = "Hello"; }
उत्पादन का उत्पादन:
true true true true false true
JVMs
JVMS 7 5.1 का कहना है कि इंटर्निंग को एक समर्पित CONSTANT_String_info
संरचना के साथ जादुई और कुशलता से लागू किया जाता है (अधिकांश अन्य वस्तुओं के विपरीत जो अधिक सामान्य प्रतिनिधित्व करते हैं):
एक स्ट्रिंग शाब्दिक वर्ग स्ट्रिंग के उदाहरण के लिए एक संदर्भ है, और एक वर्ग या इंटरफ़ेस के द्विआधारी प्रतिनिधित्व में एक CONSTANT_String_info संरचना (fo4.4.3) से लिया गया है। CONSTANT_String_info संरचना यूनिकोड कोड बिंदुओं के अनुक्रम को स्ट्रिंग शाब्दिक रूप देती है।
जावा प्रोग्रामिंग लैंग्वेज के लिए आवश्यक है कि समान स्ट्रिंग शाब्दिक (यानी, शाब्दिक, जिसमें कोड अंकों का समान अनुक्रम हो) को क्लास स्ट्रिंग (JLS §3.10.5) के समान उदाहरण को संदर्भित करना होगा। इसके अलावा, अगर String.intern को किसी भी स्ट्रिंग पर विधि कहा जाता है, तो परिणाम उसी वर्ग उदाहरण के लिए एक संदर्भ है जो कि यदि स्ट्रिंग एक शाब्दिक के रूप में दिखाई देता है तो उसे वापस कर दिया जाएगा। इस प्रकार, निम्नलिखित अभिव्यक्ति का मूल्य सही होना चाहिए:
("a" + "b" + "c").intern() == "abc"
एक स्ट्रिंग शाब्दिक प्राप्त करने के लिए, Java वर्चुअल मशीन CONSTANT_String_info संरचना द्वारा दिए गए कोड बिंदुओं के अनुक्रम की जांच करता है।
यदि विधि String.intern को पहले क्लास स्ट्रिंग के एक उदाहरण पर बुलाया गया है, जिसमें CONSTANT_String_info संरचना द्वारा दिए गए यूनिकोड कोड बिंदुओं का एक अनुक्रम है, तो स्ट्रिंग शाब्दिक व्युत्पत्ति का परिणाम कक्षा स्ट्रिंग के उसी उदाहरण का संदर्भ है।
अन्यथा, क्लास स्ट्रिंग का एक नया उदाहरण CONSTANT_String_ffo संरचना द्वारा दिए गए यूनिकोड कोड बिंदुओं के अनुक्रम से बना है; उस वर्ग उदाहरण का एक संदर्भ स्ट्रिंग शाब्दिक व्युत्पत्ति का परिणाम है। अंत में, नए स्ट्रिंग उदाहरण का आंतरिक तरीका लागू किया जाता है।
बाईटकोड
चलो कुछ OpenJDK 7 bytecode को कार्रवाई में इंटर्न करने के लिए विघटित करते हैं।
अगर हम सड़ जाते हैं:
public class StringPool {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a);
System.out.println(b);
System.out.println(a == c);
}
}
हमारे पास निरंतर पूल है:
#2 = String #32 // abc
[...]
#32 = Utf8 abc
और main
:
0: ldc #2 // String abc
2: astore_1
3: ldc #2 // String abc
5: astore_2
6: new #3 // class java/lang/String
9: dup
10: ldc #2 // String abc
12: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne 42
38: iconst_1
39: goto 43
42: iconst_0
43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
नोट कैसे:
0
और 3
: वहीldc #2
निरंतर लोड किया जाता है (शाब्दिक)
12
: एक नया स्ट्रिंग इंस्टेंस बनाया गया है (के साथ) #2
तर्क के रूप में)
35
: a
और c
नियमित वस्तुओं के साथ तुलना की जाती हैif_acmpne
निरंतर तार का प्रतिनिधित्व बाइटकोड पर काफी जादू है:
और ऊपर दिए गए JVMS उद्धरण से लगता है कि जब भी यूटीएफ 8 को इंगित किया जाता है, तब समान उदाहरणों को लोड किया जाता है ldc
।
मैंने खेतों के लिए इसी तरह के परीक्षण किए हैं, और:
static final String s = "abc"
के माध्यम से निरंतर तालिका को इंगित करता है कॉन्स्टेंटवैल्यू एट्रीब्यूट के
- गैर-अंतिम फ़ील्ड में वह विशेषता नहीं होती है, लेकिन फिर भी उसके साथ आरंभ किया जा सकता है
ldc
निष्कर्ष : स्ट्रिंग पूल के लिए प्रत्यक्ष बाइटकोड समर्थन है, और मेमोरी प्रतिनिधित्व कुशल है।
बोनस: इसकी तुलना इंटेगर पूल से करें , जिसमें डायरेक्ट बायटेकोड सपोर्ट नहीं है (यानी कोई CONSTANT_String_info
एनालॉग नहीं )।