स्ट्रिंग्स जावा में ऑब्जेक्ट हैं, इसलिए हम उन्हें बनाने के लिए 'नए' का उपयोग क्यों नहीं करते हैं?


104

हम आम तौर पर newकीवर्ड का उपयोग करके ऑब्जेक्ट बनाते हैं , जैसे:

Object obj = new Object();

स्ट्रिंग्स ऑब्जेक्ट हैं, फिर भी हम newउन्हें बनाने के लिए उपयोग नहीं करते हैं:

String str = "Hello World";

ऐसा क्यों है? क्या मैं एक स्ट्रिंग बना सकता हूं new?


इस सवाल पर भी आपकी नज़र होनी चाहिए stackoverflow.com/questions/456575/java-wrapper-equality-test
परिवर्तित हुआ

1
क्योंकि स्ट्रिंग शाब्दिक पहले से ही ऑब्जेक्ट हैं।
लोर्न

1
ध्यान दें कि new String(...)बड़े स्ट्रिंग्स को प्रतिस्थापित करते समय एक कार्यान्वयन विवरण को दरकिनार करने के लिए उपयोग किया जाता है। यह जावा 7 में तय किया गया था और यह आवश्यक नहीं है।
थोरबजोरन रेव एंडरसन

मैं इस पोस्ट का 100 वाँ लाइक हूँ। :)
Mukit09

जवाबों:


130

इसके अलावा, जो पहले से ही कहा गया था, स्ट्रिंग शाब्दिक [यानी, स्ट्रिंग्स जैसे "abcd"लेकिन नहीं जैसे new String("abcd")] जावा में नजरबंद हैं - इसका मतलब है कि हर बार जब आप "एब्सकांड" का संदर्भ देते हैं String, तो आपको एक नया उदाहरण के बजाय एक उदाहरण मिलता है। हर बार। तो आपके पास होगा:

String a = "abcd";
String b = "abcd";

a == b; //True

लेकिन अगर आपके पास था

String a = new String("abcd");
String b = new String("abcd");

तब यह संभव है

a == b; // False

(और यदि किसी को याद दिलाने की आवश्यकता है, तो हमेशा .equals()स्ट्रिंग्स की तुलना करने के लिए उपयोग करें; ==शारीरिक समानता के लिए परीक्षण)।

स्ट्रिंग स्ट्रिंग शाब्दिक अच्छा है क्योंकि वे अक्सर एक से अधिक बार उपयोग किए जाते हैं। उदाहरण के लिए, (contrived) कोड पर विचार करें:

for (int i = 0; i < 10; i++) {
  System.out.println("Next iteration");
}

यदि हमारे पास स्ट्रिंग्स की इंटर्निंग नहीं है, तो "अगला पुनरावृत्ति" को 10 बार तत्काल करने की आवश्यकता होगी, जबकि अब यह केवल एक बार त्वरित होगा।


1
स्ट्रिंग a = नया स्ट्रिंग ("abcd") का उपयोग करके, क्या इसका मतलब है कि समान सामग्री वाली दो स्ट्रिंग स्मृति में मौजूद हैं।
बदल दिया

1
सही - संकलक आवश्यक रूप से यह देखने के लिए जांच नहीं करेगा कि क्या इस तरह के स्ट्रिंग को पहले ही नजरबंद कर दिया गया है (हालांकि आप निश्चित रूप से एक ऐसा लिख ​​सकते हैं)।
डेनबेन

हां, यह अनुकूलन संभव है क्योंकि तार अपरिवर्तनीय हैं और इसलिए उन्हें समस्याओं के बिना साझा किया जा सकता है। साझा "asdf" हैंडलिंग 'फ्लाईवेट' डिज़ाइन पैटर्न का कार्यान्वयन है।
मैनुएल अलदाना

किसी ने नहीं कहा कि यह संभव नहीं है, केवल इसकी गारंटी नहीं है। क्या वह आपका पतन था?
डेनबेन

"== वस्तु समानता के लिए परीक्षण" से आपका क्या अभिप्राय है? यह मेरे लिए सच नहीं लगता है, लेकिन शायद आप इसका मतलब क्या है से अलग कुछ मतलब है।
दाऊद इब्न करीम

32

जावा में स्ट्रिंग्स "विशेष" वस्तुएं हैं। जावा डिजाइनरों ने समझदारी से फैसला किया कि स्ट्रिंग्स का उपयोग इतनी बार किया जाता है कि उन्हें अपने स्वयं के सिंटैक्स के साथ-साथ एक कैशिंग रणनीति की आवश्यकता होती है। जब आप यह कहकर स्ट्रिंग घोषित करते हैं:

String myString = "something";

myString "कुछ" के मूल्य के साथ स्ट्रिंग ऑब्जेक्ट का संदर्भ है। यदि आप बाद में घोषणा करते हैं:

String myOtherString = "something";

जावा इतना स्मार्ट है कि यह काम करता है कि myString और myOtherString एक ही हैं और उन्हें एक वैश्विक स्ट्रिंग तालिका में एक ही ऑब्जेक्ट के रूप में संग्रहीत करेगा। यह इस बात पर निर्भर करता है कि आप स्ट्रिंग्स को ऐसा करने के लिए संशोधित नहीं कर सकते। यह आवश्यक मेमोरी की मात्रा को कम करता है और तुलनाओं को तेज कर सकता है।

यदि, इसके बजाय, आप लिखते हैं

String myOtherString = new String("something");

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


अरे ... स्ट्रिंग स्ट्रिंगर्स के लिए कुछ प्रकार के सिंथैटिक सपोर्ट की आवश्यकता को पहचानने के लिए "अनंत ज्ञान" की आवश्यकता नहीं है। बस के बारे में हर दूसरे गंभीर प्रोग्रामिंग भाषा डिजाइन किसी प्रकार के स्ट्रिंग शाब्दिक का समर्थन करता है।
स्टीफन सी।

12
हाइपरबोले को अचेत कर दिया गया है, कप्तान :)
जेमी मैकक्रिंडल

16
String a = "abc"; // 1 Object: "abc" added to pool

String b = "abc"; // 0 Object: because it is already in the pool

String c = new String("abc"); // 1 Object

String d = new String("def"); // 1 Object + "def" is added to the Pool

String e = d.intern(); // (e==d) is "false" because e refers to the String in pool

String f = e.intern(); // (f==e) is "true" 

//Total Objects: 4 ("abc", c, d, "def").

आशा है कि इससे कुछ संदेह दूर होंगे। :)


स्ट्रिंग डी = नया स्ट्रिंग ("डीईएफ"); // 1 ऑब्जेक्ट + "डीफ़" को पूल में जोड़ा जाता है -> यहाँ "डीएफ़" को पूल में जोड़ा जाएगा, अगर यह अभी तक वहां नहीं है
सुथर्टन

@southerton अर्थहीन। यह पहले से ही पूल में है। इसे कंपाइलर ने वहां रखा था।
लोर्न

@EJP क्यों (e == d) यहाँ गलत है? वे दोनों पूल में एक ही वस्तु "डीफ़" का हवाला दे रहे हैं?
राजा

स्ट्रिंग सी = नया स्ट्रिंग ("एबीसी"); // 1 ऑब्जेक्ट ... क्या यह कथन सही है? यदि "एबीसी" पहले से ही निरंतर पूल से संदर्भित है तो अंतर विधि का क्या उपयोग है?
प्रशान्त देवबदवार

6

यह एक शॉर्टकट है। यह मूल रूप से ऐसा नहीं था, लेकिन जावा ने इसे बदल दिया।

यह FAQ इसके बारे में संक्षेप में बात करता है। जावा विनिर्देश गाइड इसके बारे में भी बात करता है। लेकिन मैं इसे ऑनलाइन नहीं ढूँढ सकता।


2
टूटा हुआ लिंक, और मुझे किसी अन्य सबूत के बारे में पता नहीं है कि यह कभी भी बदल गया था।
लोर्ने का

1
@EJP यदि यह उपयोगी है तो यह अभी भी वेकबैक मशीन में है।
अर्जन

6

स्ट्रिंग कुछ हद तक अनुकूलन के अधीन है (बेहतर वाक्यांश के लिए)। ध्यान दें कि स्ट्रिंग में ऑपरेटर ओवरलोडिंग (+ ऑपरेटर के लिए) भी है - अन्य वस्तुओं के विपरीत। इसलिए यह बहुत खास मामला है।


1
The + वास्तव में एक ऑपरेटर है जो StringBuilder.append (..) कॉल में अनुवादित है।
व्हिस्की सियार

5

हम आम तौर पर अनावश्यक वस्तुओं को बनाने से बचने के लिए स्ट्रिंग शाब्दिक का उपयोग करते हैं। यदि हम String ऑब्जेक्ट बनाने के लिए नए ऑपरेटर का उपयोग करते हैं, तो यह हर बार नई ऑब्जेक्ट बनाएगा।

उदाहरण:

String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);

स्मृति में उपरोक्त कोड के लिए:

यहां छवि विवरण दर्ज करें


2

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

    String a = "foo";
    String b = "foo";
    System.out.println(a == b); // true
    String c = new String(a);
    System.out.println(a == c); // false
    c = c.intern();
    System.out.println(a == c); // true

जब क्लास लोडर एक कक्षा को लोड करता है, तो सभी स्ट्रिंग स्थिरांक को स्ट्रिंग पूल में जोड़ा जाता है।


"डबल उद्धरण कंपाइलर को स्ट्रिंग ऑब्जेक्ट बनाने का कारण बनता है।"
अघोषित

0

सिंथेटिक चीनी।

String s = new String("ABC");

सिंटैक्स अभी भी उपलब्ध है।


1
यह बिलकुल सही नहीं है। s = नया स्ट्रिंग ("एबीसी") आपको एस = "एबीसी" के समान परिणाम नहीं देगा। देखें डैनबेन की टिप्पणी।
स्टीव बी।

2
इसके अलावा, कुछ विडंबना यह है कि यह पहली बार "एबीसी" इनलाइन का प्रतिनिधित्व करते हुए एक स्ट्रिंग उदाहरण बनाएगा - और फिर पास करने के लिए कंस्ट्रक्टर कॉल के तर्क के रूप में जो वापसी को समान मूल्य का स्ट्रिंग बना देगा।
आंद्रेज डोयले

1
इस निर्माता के लिए वैध उपयोग मामला है String small = new String(huge.substring(int, int));, जो आपको char[]मूल hugeस्ट्रिंग से अंतर्निहित बड़े को रीसायकल करने की अनुमति देता है ।
पास्कल थिवेंट

1
@PascalThivent हाँ, लेकिन अब जावा 8 के साथ नहीं। यह एरेज़ को अब साझा नहीं करता है (अन्य अनुकूलन के लिए तैयारी में जैसे G1 या आगामी स्ट्रिंग कम्प्रेशन के साथ स्वत: स्ट्रिंग डिडुप्लीकेशन)।
eckes

@AndrzejDoyle सही नहीं है। संकलक शाब्दिक के लिए वस्तु बनाता है।
लोर्न

0

आप अभी भी उपयोग कर सकते हैं new String("string"), लेकिन स्ट्रिंग स्ट्रिंगल के बिना नए तार बनाना कठिन होगा ... आपको वर्ण सरणियों या बाइट्स का उपयोग करना होगा :-) स्ट्रिंग शाब्दिक में एक अतिरिक्त संपत्ति है: किसी भी वर्ग बिंदु से एक ही स्ट्रिंग के सभी एक ही स्ट्रिंग शाब्दिक उदाहरण (वे नजरबंद हैं)।


0

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


0

के साथ एक नया स्ट्रिंग बनाने के लिए स्वतंत्र महसूस करें

String s = new String("I'm a new String");

सामान्य संकेतन s = "new String";कमोबेश एक सुविधाजनक शॉर्टकट है - जिसका उपयोग उन दुर्लभ दुर्लभ मामलों को छोड़कर प्रदर्शन कारणों के लिए किया जाना चाहिए, जहां आपको वास्तव में स्ट्रिंग्स की आवश्यकता होती है जो समीकरण के लिए अर्हता प्राप्त करते हैं

(string1.equals(string2)) && !(string1 == string2)

संपादित करें

टिप्पणी के जवाब में: यह एक सलाह होने का इरादा नहीं था, लेकिन प्रश्नकर्ता थीसिस के लिए केवल एक सीधी प्रतिक्रिया है, कि हम स्ट्रिंग्स के लिए 'नए' कीवर्ड का उपयोग नहीं करते हैं , जो केवल सच नहीं है। आशा है कि यह संपादित (ऊपर सहित) इसे थोड़ा स्पष्ट करता है। BTW - SO पर उपर्युक्त प्रश्न के लिए कुछ अच्छे और बहुत बेहतर उत्तर हैं।


4
-1 - बुरी सलाह। new String(...)एक विशिष्ट पहचान के साथ एक स्ट्रिंग बनाने के लिए आपको अपने आवेदन की आवश्यकता का उपयोग करने के लिए "स्वतंत्र महसूस" नहीं करना चाहिए ।
स्टीफन सी।

1
मुझे पता है। स्पष्टीकरण के लिए पोस्ट को संपादित किया।
एंड्रियास डॉक

0

शाब्दिक पूल में कोई स्ट्रिंग्स है जो कीवर्ड का उपयोग किए बिना बनाई गई थी new

एक अंतर है: स्ट्रिंग के बिना नए संदर्भ को स्ट्रिंग शाब्दिक पूल में संग्रहीत किया जाता है और नए के साथ स्ट्रिंग कहते हैं कि वे ढेर स्मृति में हैं।

नए के साथ स्ट्रिंग किसी अन्य ऑब्जेक्ट की तरह स्मृति में कहीं और हैं।


0

क्योंकि स्ट्रिंग जावा में एक अपरिवर्तनीय वर्ग है।

अब यह अपरिवर्तनीय क्यों है? चूंकि स्ट्रिंग अपरिवर्तनीय है, इसलिए इसे कई थ्रेड्स के बीच साझा किया जा सकता है और हमें स्ट्रिंग ऑपरेशन को बाहरी रूप से सिंक्रनाइज़ करने की आवश्यकता नहीं है। जैसा कि स्ट्रिंग को क्लास लोडिंग तंत्र में भी उपयोग किया जाता है। इसलिए यदि स्ट्रिंग परस्पर थी तो java.io.writer को abc.xyz.mywriter में बदला जा सकता था


0
TString obj1 = new TString("Jan Peter");                
TString obj2 = new TString("Jan Peter");                    

if (obj1.Name == obj2.Name)                 
    System.out.println("True");
else                
    System.out.println("False");

आउटपुट:

सच

मैंने दो अलग-अलग ऑब्जेक्ट बनाए, दोनों में एक फ़ील्ड (Ref) 'नाम' है। तो इस मामले में भी "जान पीटर" साझा किया जाता है, अगर मैं जिस तरह से जावा सौदों को समझता हूं ..


0

खैर स्ट्रैपपूल जावा में द हैशमप का उपयोग करके कार्यान्वित किया जाता है। यदि हम हमेशा एक नए कीवर्ड के साथ बना रहे हैं, तो स्ट्रिंग पूल में खोज नहीं कर रहे हैं और इसके लिए एक नई मेमोरी बना रहे हैं जिसकी बाद में आवश्यकता हो सकती है यदि हमारे पास मेमोरी सघन ऑपरेशन चल रहा है और यदि हम नए कीवर्ड के साथ सभी स्ट्रिंग्स बना रहे हैं जो प्रदर्शन को प्रभावित करेगा हमारे आवेदन की। तो स्ट्रिंग बनाने के लिए नए कीवर्ड का उपयोग नहीं करने की इसकी सलाह दी जाती है क्योंकि तब यह केवल स्ट्रिंग पूल में जाएगा जो बदले में एक हशमैप है, (मेमोरी सेव की गई, कल्पना करें कि अगर हमारे पास बहुत सारे स्ट्रिंग्स नए कीवर्ड के साथ बनाए गए हैं) तो इसे संग्रहीत किया जाएगा और यदि स्ट्रिंग पहले से ही इसका संदर्भ मौजूद है (जो आमतौर पर स्टैक मेमोरी में रहता है) को नए बनाए गए स्ट्रिंग पर लौटा दिया जाएगा। तो इसका प्रदर्शन सुधारने के लिए किया गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.