JLS
जेएलएस द्वारा अवधारणा को "इंटर्निंग" कहा जाता है।
JLS 7 3.10.5 से प्रासंगिक मार्ग :
इसके अलावा, एक स्ट्रिंग शाब्दिक हमेशा कक्षा स्ट्रिंग के एक ही उदाहरण को संदर्भित करता है। ऐसा इसलिए है क्योंकि स्ट्रिंग शाब्दिक - या, अधिक सामान्यतः, स्ट्रिंग्स जो निरंतर अभिव्यक्तियों (§15.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 संरचना (fo4.4.3) से लिया गया है। CONSTANT_String_info संरचना यूनिकोड कोड बिंदुओं के अनुक्रम को स्ट्रिंग शाब्दिक रूप देता है।
जावा प्रोग्रामिंग लैंग्वेज के लिए आवश्यक है कि समान स्ट्रिंग शाब्दिक (यानी, शाब्दिक जिसमें कोड अंकों का समान अनुक्रम हो) को कक्षा स्ट्रिंग (JLS §3.10.5) के समान उदाहरण को संदर्भित करना होगा। इसके अलावा, यदि String.intern को किसी भी स्ट्रिंग पर विधि कहा जाता है, तो परिणाम उसी वर्ग उदाहरण के लिए एक संदर्भ है जो कि यदि स्ट्रिंग एक शाब्दिक के रूप में दिखाई देता है तो उसे लौटा दिया जाएगा। इस प्रकार, निम्नलिखित अभिव्यक्ति का मूल्य सही होना चाहिए:
("a" + "b" + "c").intern() == "abc"
एक स्ट्रिंग शाब्दिक प्राप्त करने के लिए, जावा वर्चुअल मशीन CONSTANT_String_info संरचना द्वारा दिए गए कोड बिंदुओं के अनुक्रम की जांच करता है।
यदि विधि String.intern को पहले कक्षा स्ट्रिंग के एक उदाहरण पर बुलाया गया है, जिसमें CONSTANT_String_info संरचना द्वारा दिए गए यूनिकोड कोड बिंदुओं का एक अनुक्रम है, तो स्ट्रिंग शाब्दिक व्युत्पत्ति का परिणाम कक्षा स्ट्रिंग के उसी उदाहरण का संदर्भ है।
अन्यथा, क्लास स्ट्रिंग का एक नया उदाहरण CONSTANT_String_ffo संरचना द्वारा दिए गए यूनिकोड कोड बिंदुओं के अनुक्रम से बना है; उस वर्ग उदाहरण का एक संदर्भ स्ट्रिंग शाब्दिक व्युत्पत्ति का परिणाम है। अंत में, नए स्ट्रिंग उदाहरण का आंतरिक तरीका लागू किया जाता है।
बाईटकोड
यह भी OpenJDK 7 पर बायोटेक कार्यान्वयन को देखने के लिए शिक्षाप्रद है।
अगर हम सड़ जाते हैं:
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एनालॉग नहीं )।