2011-09-10 6 views
6

मैं निम्नलिखित जावा कोड:कितने स्ट्रिंग वस्तुओं बनाया जाएगा

public String makinStrings() { 
    String s = "Fred"; 
    s = s + "47"; 
    s = s.substring(2, 5); 
    s = s.toUpperCase(); 
    return s.toString(); 
} 

सवाल किसी भी तरह सरल है: कितने String वस्तुओं जब इस पद्धति शुरू हो जाती है बनाया जाएगा?

शुरुआत में मैंने जवाब दिया कि 5 स्ट्रिंग ऑब्जेक्ट्स बनाए गए हैं, लेकिन मेरी पुस्तक का जवाब कहता है कि केवल 3 ऑब्जेक्ट्स बनाए जाते हैं और कोई स्पष्टीकरण नहीं दिया जाता है (यह एक एससीजेपी प्रश्न है)।

मेरे दृष्टिकोण से 5 ऑब्जेक्ट्स हैं: "फ्रेड", "47", "फ्रेड 47", "एड 4", "ईडी 4"।

मैं भी यही जवाब 3.

+3

मैं कल्पना संकलक पहले दो बयानों इनलाइन और अंतिम (अनावश्यक) विधि कॉल निकाल देंगे। यह आपको "फ्रेड 47", "एड 4", "ईडी 4" के साथ छोड़ देता है। –

+1

@ जेरेड 'एस * संकलन-समय निरंतर अभिव्यक्ति नहीं है * इसलिए ऐसा नहीं होता है। (कोड संकलित करें और 'javap -c', या यहां तक ​​कि' तार 'का उपयोग करें। –

+0

[जावा - कितने स्ट्रिंग ऑब्जेक्ट्स?] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/17898236/java-how-many -स्ट्रिंग-ऑब्जेक्ट्स) –

उत्तर

15

"फ्रेड" और "47" शाब्दिक पूल स्ट्रिंग से आएगा के साथ, एक SCJP सिमुलेशन परीक्षा पर इस सवाल का पाया। इस प्रकार वे विधि लागू होने पर बनाए जाएंगे। इसके बजाय उन्हें कक्षा में लोड होने पर रखा जाएगा (या इससे पहले, यदि अन्य वर्ग समान मूल्य वाले स्थिरांक का उपयोग करते हैं)।

"फ्रेड 47", "एड 4" और "ईडी 4" 3 String ऑब्जेक्ट्स हैं जो प्रत्येक विधि आमंत्रण पर बनाए जाएंगे।

+0

पहली विधि आमंत्रण के बाद "फ्रेड 47", "ed4" और "ED4" स्ट्रिंग शाब्दिक पूल में भी नहीं होगा? मेरा मानना ​​है कि जेरेड का उत्तर/टिप्पणी सही है (+1), क्योंकि मुझे लगता है कि सभी कंपाइलर्स इन सरल इनलाइनिंग करते हैं। यही कारण है कि तारों को जोड़ना इतना महंगा नहीं है (हालांकि अभी भी कुछ हद तक)। – DaveFar

+1

यह [स्पष्ट रूप से कानूनी] है (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#19124) एक जेवीएम के लिए स्ट्रिंग अक्षर को तत्काल लोड करने के लिए जब उन्हें पहले लोड किया जाता है निरंतर पूल से, उन्हें कक्षा लोड समय पर आसानी से लोड करने की बजाय। मुझे नहीं लगता कि यह कार्यान्वयन विवरण मूल प्रश्न के लिए वास्तव में प्रासंगिक है, लेकिन यह मामूली बात का एक दिलचस्प टुकड़ा है। –

+0

नोट करें कि पहली दो पंक्तियों को एक ही कथन के रूप में लिखा गया था, "फ्रेड 47" का उपयोग सीधे "फ्रेड" + "47" के रूप में किया जाएगा * एक * संकलन-समय निरंतर अभिव्यक्ति * है। साथ ही, लाइब्रेरी को अलग-अलग कार्यान्वित किया जा सकता है और स्ट्रिंग ऑब्जेक्ट्स की एक अलग संख्या का उत्पादन करना संभव है। –

2

कार्यक्रमों में उनके कोड में बहुत सारे स्ट्रिंग अक्षर शामिल होते हैं। जावा में, इन स्थिरांक को दक्षता के लिए स्ट्रिंग तालिका नामक किसी चीज़ में एकत्र किया जाता है। उदाहरण के लिए, यदि आप दस अलग-अलग स्थानों में स्ट्रिंग "Name: " का उपयोग करते हैं, तो JVM (आमतौर पर) में उस स्ट्रिंग का केवल एक उदाहरण होता है और सभी दस स्थानों में जहां इसका उपयोग किया जाता है, संदर्भ सभी एक उदाहरण को इंगित करते हैं। यह स्मृति बचाता है।

यह अनुकूलन संभव है क्योंकि Stringअपरिवर्तनीय है। यदि स्ट्रिंग को बदलना संभव था, तो इसे एक स्थान बदलना मतलब होगा कि यह दूसरे नौ में भी बदल जाएगा। यही कारण है कि स्ट्रिंग को बदलने वाला कोई भी ऑपरेशन एक नया उदाहरण देता है।

String s = "boink"; 
s.toUpperCase(); 
System.out.println(s); 

यह boink, नहीं BOINK प्रिंट: यह यदि आप ऐसा करते है कि क्यों। एक ही char[] पर विचारों, बस एक टुकड़ा का उपयोग करके अपने चरित्र डेटा के लिए एक ही अंतर्निहित char[] करने के लिए java.lang.Stringमई बिंदु के कई उदाहरण, दूसरे शब्दों में, वे अलग हो सकता है:

अब एक और मुश्किल सा सरणी का फिर, दक्षता के लिए एक अनुकूलन। substring() विधि उन मामलों में से एक है जहां यह होता है।

  • स्ट्रिंग "Fred" स्ट्रिंग तालिका से लिया जाता है:

    s1 = "Fred47"; 
    
    //String s1: data=[ 'F', 'r', 'e', 'd', '4', '7'], offset=0, length=6 
    //     ^........................^ 
    
    s2 = s1.substring(2, 5); 
    
    //String s2: data=[ 'F', 'r', 'e', 'd', '4', '7'], offset=2, length=3 
    //        ^.........^ 
    // the two strings are sharing the same char[]! 
    

    अपने SCJP सवाल में, यह सब करने के लिए निर्भर करता है।

  • स्ट्रिंग "47" स्ट्रिंग तालिका से लिया गया है।
  • स्ट्रिंग "Fred47" विधि कॉल के दौरान बनाई गई है।// 1
  • स्ट्रिंग "ed4" विधि कॉल के दौरान बनाई गई है, रूप "Fred47" // 2
  • ही समर्थन सरणी साझा करने स्ट्रिंग "ED4" विधि कॉल के दौरान बनाई गई है। // 3
  • s.toString() कोई नया निर्माण नहीं करता है, यह केवल this देता है।

एक यह सब के दिलचस्प बढ़त मामला: चुनें यदि आप एक बहुत लंबा स्ट्रिंग है कि क्या होता है, उदाहरण के लिए, इंटरनेट से ली गई एक वेब पेज, मान लें कि char[] की लंबाई दो मेगाबाइट है करते हैं। यदि आप substring(0, 4) लेते हैं, तो आपको एक नया स्ट्रिंग मिलता है जो दिखता है जैसे कि यह केवल चार वर्ण लंबा है, लेकिन यह अभी भी उन दो मेगाबाइट बैकिंग डेटा साझा करता है। असली दुनिया में यह सब सामान्य नहीं है, लेकिन यह स्मृति का एक बड़ा अपशिष्ट हो सकता है! (दुर्लभ) मामले में आप इसे किसी समस्या के रूप में चलाते हैं, तो आप नई, छोटी बैकिंग सरणी के साथ स्ट्रिंग बनाने के लिए new String(hugeString.substring(0, 4)) का उपयोग कर सकते हैं।

अंत में, intern() पर कॉल करके रनटाइम पर स्ट्रिंग तालिका में एक स्ट्रिंग को मजबूर करना संभव है। इस मामले में मूल नियम: ऐसा मत करो। विस्तारित नियम: तब तक ऐसा न करें जब तक आप यह सुनिश्चित करने के लिए मेमोरी प्रोफाइलर का उपयोग नहीं करते हैं कि यह एक उपयोगी अनुकूलन है।

+0

यह गलत है। स्ट्रिंग स्थिरांक में से कोई भी "स्ट्रिंग पूल" से नहीं आ रहा है, वे सभी कक्षाओं के निरंतर पूल से आते हैं। यदि कई वर्ग वर्गों में "फ्रेड 47" जैसी ही शाब्दिक स्थिरता का उपयोग किया जाता है, तो उनमें से प्रत्येक के निरंतर पूल में समान स्थिरता होती है। चिप मैककॉर्मिक के जवाब के बाइटकोड देखें। –

2

जावप आउटपुट के आधार पर, ऐसा लगता है कि एक स्ट्रिंगबिल्डर बनाया गया है, स्ट्रिंग नहीं। तब तीन स्ट्रिंग्स हैं जिन्हें substring(), ToUpperCase() और toString() के लिए बुलाया जाता है।

अंतिम कॉल अनावश्यक नहीं है क्योंकि यह स्ट्रिंगबिल्डर को स्ट्रिंग में बदल देता है।

>javap -c Test 
Compiled from "Test.java" 

public java.lang.String makinStrings(); 
Code: 
0: ldc  #5; //String Fred 
2: astore_1 
3: new  #6; //class java/lang/StringBuilder 
6: dup 
7: invokespecial #7; //Method java/lang/StringBuilder."<init>":()V 
10: aload_1 
11: invokevirtual #8; //Method java/lang/StringBuilder.append: (Ljava/lang/String;)Ljava/lang/StringBuilder; 
14: ldc  #9; //String 47 
16: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
19: invokevirtual #10; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
22: astore_1 
23: aload_1 
24: iconst_2 
25: iconst_5 
26: invokevirtual #11; //Method java/lang/String.substring:(II)Ljava/lang/String; 
29: astore_1 
30: aload_1 
31: invokevirtual #12; //Method java/lang/String.toUpperCase:()Ljava/lang/String; 
34: astore_1 
35: aload_1 
36: invokevirtual #13; //Method java/lang/String.toString:()Ljava/lang/String; 
39: areturn 

}

+0

तो teh सही उत्तर है: 3. या मैं miscounting हूँ? –

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