जावा स्ट्रिंग्स: "स्ट्रिंग s = नया स्ट्रिंग (" मूर्खतापूर्ण ");)


85

मैं जावा सीखने वाला एक C ++ लड़का हूं। मैं प्रभावी जावा पढ़ रहा हूँ और मुझे कुछ उलझन में है। यह इस तरह कोड लिखने के लिए कभी नहीं कहता है:

String s = new String("silly");

क्योंकि यह अनावश्यक Stringवस्तुओं का निर्माण करता है। लेकिन इसके बजाय इसे इस तरह लिखा जाना चाहिए:

String s = "No longer silly";

ठीक है अब तक ... हालांकि, इस वर्ग को दिया:

public final class CaseInsensitiveString {
    private String s;
    public CaseInsensitiveString(String s) {
        if (s == null) {
            throw new NullPointerException();
        }
        this.s = s;
    }
    :
    :
}

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
  1. पहला बयान क्यों ठीक है? यह नहीं होना चाहिए

    CaseInsensitiveString cis = "Polish";

  2. मैं CaseInsensitiveStringइस तरह का व्यवहार कैसे कर सकता हूं Stringताकि उपर्युक्त कथन ठीक है (विस्तार के साथ और बिना String)? यह स्ट्रिंग के बारे में क्या है जो इसे ठीक करने के लिए इसे शाब्दिक रूप से पारित करने में सक्षम बनाता है? मेरी समझ से जावा में कोई "कॉपी कंस्ट्रक्टर" अवधारणा नहीं है?


2
स्ट्रिंग str1 = "फू"; स्ट्रिंग str2 = "फू"; Str1 और str2 दोनों का संबंध एक ही स्ट्रिंग वस्तु से है, "foo", b'coz Java के लिए StringPool में स्ट्रिंग्स का प्रबंधन करता है, इसलिए एक नया वैरिएबल उसी स्ट्रिंग को संदर्भित करता है, यह एक और नहीं बनाता है, बल्कि एक ही एलरडिए में मौजूद है StringPool। लेकिन जब हम ऐसा करते हैं: स्ट्रिंग str1 = नया स्ट्रिंग ("फू"); स्ट्रिंग str2 = नया स्ट्रिंग ("फू"); यहाँ str1 और str2 दोनों अलग-अलग ऑब्जेक्ट्स के हैं, b'coz new String () जबरदस्ती एक नया स्ट्रिंग ऑब्जेक्ट बनाते हैं।
आकाश ५२ Ak Ak

जवाबों:


110

Stringभाषा का एक विशेष अंतर्निहित वर्ग है। यह केवल उस Stringवर्ग के लिए है जिसमें आपको कहने से बचना चाहिए

String s = new String("Polish");

क्योंकि शाब्दिक "Polish"पहले से ही प्रकार का है String, और आप एक अतिरिक्त अनावश्यक वस्तु बना रहे हैं। किसी अन्य वर्ग के लिए, कह रही है

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

सही (और केवल, इस मामले में) बात करने के लिए है।


8
एक दूसरा बिंदु यह है कि संकलक इंटर्नग / प्रचार-सामान को स्ट्रिंग शाब्दिकों के साथ जोड़ सकता है, जो कि "स्ट्रिंग (शाब्दिक)" जैसे अजीब समारोह के साथ जरूरी नहीं है
टेटा

4
चूंकि आपको कभी फोन नहीं करना चाहिए new String("foo"), आप खुद से पूछ सकते हैं कि कंस्ट्रक्टर क्यों new String(String)मौजूद है। इसका उत्तर यह है कि इसके लिए कभी-कभी एक अच्छा उपयोग होता है: stackoverflow.com/a/390854/1442870
एन्वेल्ड किया गया

FYI करें, टेटा के ऊपर की टिप्पणी ने "इंटर्निंग" शब्द को गलत बताया, जैसा कि स्ट्रिंग इंटर्निंग में है
बेसिल बोर्ख

56

मेरा मानना ​​है कि नए स्ट्रिंग ("फू") के बजाय शाब्दिक रूप (यानी, "फू" का उपयोग करने का मुख्य लाभ यह है कि सभी स्ट्रिंग शाब्दिक वीएम द्वारा 'नजरबंद' हैं। दूसरे शब्दों में, इसे एक पूल में जोड़ा जाता है जैसे कि कोई अन्य कोड जो समान स्ट्रिंग बनाता है वह नया उदाहरण बनाने के बजाय पूल किए गए स्ट्रिंग का उपयोग करेगा।

वर्णन करने के लिए, निम्नलिखित कोड पहली पंक्ति के लिए सही होगा, लेकिन दूसरे के लिए गलत होगा:

System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));

14
इसी तरह, यही कारण है कि फाइंडबग्स आपको "इंटर्गर.वेल्यूऑफ (एन)" के साथ "नए इंटेगर (एन)" को बदलने के लिए कहता है - उस इंटर्निंग के कारण।
पॉल टॉम्बलिन

6
आपको "फू" == नया स्ट्रिंग ("फू") भी जोड़ना चाहिए। इंटर्न ()
जेम्स स्कैच

4
एक सुधार: स्ट्रिंग शाब्दिकों को संकलक द्वारा एक ही संदर्भ में इंगित करने के लिए बनाया गया है, वीएम नहीं। VM रनिंग के समय स्ट्रींग ऑब्जेक्ट को इंटर्न कर सकता है, इसलिए दूसरी लाइन सही या गलत हो सकती है!
क्रेग पी। मोटलिन

1
@ मोलिन: मुझे यकीन नहीं है कि यह सही है। स्ट्रिंग क्लास के लिए javadoc का कहना है कि "सभी शाब्दिक तार और स्ट्रिंग-मूल्यवान स्थिर अभिव्यक्तियों को नजरबंद किया गया है"। इसलिए हम शाब्दिक रूप से नजरबंद होने पर भरोसा कर सकते हैं, जिसका अर्थ है कि "फू" == "फू" को हमेशा सही होना चाहिए।
लीघ

3
@Leigh हाँ, शाब्दिक नजरबंद हैं, लेकिन संकलक द्वारा और वीएम नहीं। मोटलिन को जो मिल रहा है, वह यह है कि वीएम अतिरिक्त रूप से स्ट्रांग हो सकता है, इस प्रकार, चाहे नया स्ट्रिंग ("बार") == नया स्ट्रिंग ("बार") -> गलत कार्यान्वयन पर निर्भर है।
हारून मेंपा

30

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

अगर आप लिखेंगे

String s = "Polish";
String t = "Polish";

तब s और t वास्तव में एक ही ऑब्जेक्ट को संदर्भित करते हैं, और s == t सही लौटेगा, "==" के लिए "पढ़ी गई वस्तुओं के लिए" एक ही ऑब्जेक्ट है "(या, वैसे भी, मैं" निश्चित नहीं हूं कि यह हिस्सा है या नहीं वास्तविक भाषा कल्पना या बस संकलक कार्यान्वयन का एक विवरण-तो शायद इस पर भरोसा करना सुरक्षित नहीं है)।

अगर आप लिखेंगे

String s = new String("Polish");
String t = new String("Polish");

तब s! = t (क्योंकि आपने स्पष्ट रूप से एक नया स्ट्रिंग बनाया है) हालांकि s.equals (t) सही लौटेगा (क्योंकि स्ट्रिंग इस व्यवहार को बराबर जोड़ता है)।

जिस चीज को आप लिखना चाहते हैं,

CaseInsensitiveString cis = "Polish";

काम नहीं कर सकते क्योंकि आप सोच रहे हैं कि उद्धरण आपकी वस्तु के लिए शॉर्ट-सर्किट कंस्ट्रक्टर के कुछ प्रकार हैं, जब वास्तव में यह केवल सादे पुराने java.lang.Strings के लिए काम करता है।


+1 अपरिवर्तनीयता का उल्लेख करने के लिए, जो मेरे लिए जावा में वास्तविक कारण है strA = strB, इसके बजाय लिखता है strA = new String(strB)। यह वास्तव में स्ट्रिंग इंटर्निंग के साथ बहुत कुछ करने की ज़रूरत नहीं है।
kritzikratzi

उन्हें संदर्भ गिनती द्वारा नियंत्रित नहीं किया जाता है। JLS द्वारा स्ट्रिंग पूलिंग आवश्यक है।
लोर्न

20
String s1="foo";

शाब्दिक पूल में जाएगा और s1 संदर्भित करेगा।

String s2="foo";

इस बार यह जाँच करेगा कि "फू" शाब्दिक पहले से ही स्ट्रिंगपूल में उपलब्ध है या नहीं के रूप में अब मौजूद है इसलिए s2 समान शाब्दिक का उल्लेख करेगा।

String s3=new String("foo");

"foo" शाब्दिक को पहले स्ट्रिंगपूल में बनाया जाएगा, फिर स्ट्रिंग आरजी कंस्ट्रक्टर के माध्यम से स्ट्रिंग ऑब्जेक्ट बनाया जाएगा यानी नए ऑपरेटर के माध्यम से ऑब्जेक्ट निर्माण के कारण ढेर में "फू" तब s3 इसे संदर्भित करेगा।

String s4=new String("foo");

S3 के समान

इसलिए System.out.println(s1==s2);// **true** due to literal comparison.

तथा System.out.println(s3==s4);// **false** due to object

तुलना (s3 और s4 ढेर में विभिन्न स्थानों पर बनाई गई है)


1
पाठ के लिए उद्धरण स्वरूपण का उपयोग न करें, जो उद्धृत नहीं है, और कोड के लिए कोड स्वरूपण का उपयोग न करें।
लोर्न

12

Stringजावा में विशेष हैं - वे अपरिवर्तनीय हैं, और स्ट्रिंग स्थिरांक स्वचालित रूप से Stringवस्तुओं में बदल जाते हैं।

आपके SomeStringClass cis = "value"उदाहरण के लिए किसी अन्य वर्ग पर लागू होने का कोई रास्ता नहीं है ।

न ही आप विस्तार कर सकते हैं String, क्योंकि यह घोषित किया गया है final, जिसका अर्थ है कि कोई उप-वर्ग की अनुमति नहीं है।


7

जावा तार दिलचस्प हैं। ऐसा लगता है कि प्रतिक्रियाओं ने कुछ दिलचस्प बिंदुओं को कवर किया है। यहाँ मेरे दो सेंट हैं।

तार अपरिवर्तनीय हैं (आप उन्हें कभी नहीं बदल सकते)

String x = "x";
x = "Y"; 
  • पहली पंक्ति एक चर x बनाएगी जिसमें स्ट्रिंग मान "x" होगा। JVM स्ट्रिंग मानों के अपने पूल को देखेगा और देखेगा कि "x" मौजूद है या नहीं, यदि यह होता है, तो यह चर x को इंगित करेगा, यदि यह मौजूद नहीं है, तो यह इसे बनाएगा और फिर असाइनमेंट करेगा
  • दूसरी पंक्ति "x" के संदर्भ को हटा देगी और यह देखेगी कि क्या "Y" स्ट्रिंग मानों के पूल में मौजूद है। यदि यह मौजूद है, तो यह इसे असाइन करेगा, यदि यह नहीं है, तो यह इसे पहले असाइनमेंट बनाएगा। जैसे कि स्ट्रिंग मानों का उपयोग किया जाता है या नहीं, स्ट्रिंग मानों के पूल में मेमोरी स्पेस को पुनः प्राप्त किया जाएगा।

स्ट्रिंग तुलना आप क्या तुलना कर रहे हैं पर आकस्मिक हैं

String a1 = new String("A");

String a2 = new String("A");
  • a1 बराबर नही हैं a2
  • a1 तथा a2 वस्तु संदर्भ हैं
  • जब स्ट्रिंग स्पष्ट रूप से घोषित किया जाता है, तो नए उदाहरण बनाए जाते हैं और उनके संदर्भ समान नहीं होंगे।

मुझे लगता है कि आप केसेंसेंसिव क्लास का उपयोग करने की कोशिश कर रहे हैं। तार अकेले छोड़ दो। आप वास्तव में इस बात की परवाह करते हैं कि आप मूल्यों को कैसे प्रदर्शित करते हैं या तुलना करते हैं। स्ट्रिंग को प्रारूपित करने या तुलना करने के लिए किसी अन्य वर्ग का उपयोग करें।

अर्थात

TextUtility.compare(string 1, string 2) 
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)

चूँकि आप क्लास बना रहे हैं, आप तुलना वही कर सकते हैं जो आप चाहते हैं - पाठ मूल्यों की तुलना करें।


संकलक स्ट्रिंग पूल बनाता है, जेवीएम नहीं। चर में ऑब्जेक्ट्स नहीं होते हैं, वे उन्हें संदर्भित करते हैं। स्ट्रिंग लिटरल्स के लिए स्ट्रिंग पूल का स्थान कभी भी पुनः प्राप्त नहीं हुआ है।
लोर्न

6

आप नहीं कर सकते। जावा में डबल-कोट्स में चीजें विशेष रूप से संकलक द्वारा स्ट्रिंग्स के रूप में पहचानी जाती हैं, और दुर्भाग्य से आप इसे ओवरराइड नहीं कर सकते हैं (या विस्तारित करें java.lang.String- घोषित किया गया है final)।


फाइनल यहाँ एक लाल हेरिंग है। अगर स्ट्रिंग अंतिम नहीं थी, तब भी स्ट्रिंग का विस्तार करना इस मामले में उसकी मदद नहीं करेगा।
डार्रोन

1
मुझे लगता है कि आप सौभाग्य से आप इसे ओवरराइड नहीं कर सकते। :)
क्रेग पी। मोटलिन

@ मैटलिन: हा! आप सही हो सकते हैं। मुझे लगता है कि मैंने कहीं पढ़ा है कि जावा को डिज़ाइन किया गया था कि वह किसी को भी कभी भी कुछ भी करने से रोकने के लिए जानबूझकर इस तरह से दिलचस्प कुछ भी कर सकता है ...
दान विंटन

6

अपने प्रश्न का उत्तर देने का सबसे अच्छा तरीका आपको "स्ट्रिंग निरंतर पूल" से परिचित कराना होगा। जावा में स्ट्रिंग ऑब्जेक्ट अपरिवर्तनीय होते हैं (अर्थात उनके मानों को एक बार शुरू करने के बाद उन्हें बदला नहीं जा सकता है), इसलिए जब एक स्ट्रिंग ऑब्जेक्ट को संपादित करते हुए आप एक नया संपादित स्ट्रिंग ऑब्जेक्ट बनाते हैं, तो पुरानी वस्तु बस एक विशेष मेमोरी के चारों ओर तैरती है जिसे "स्ट्रिंग" कहा जाता है। निरंतर पूल ”। द्वारा एक नई स्ट्रिंग ऑब्जेक्ट बनाना

String s = "Hello";

केवल पूल में एक स्ट्रिंग ऑब्जेक्ट बनाएगा और संदर्भ s इसे संदर्भित करेगा, लेकिन उपयोग करके

String s = new String("Hello");

आप दो स्ट्रिंग ऑब्जेक्ट बनाते हैं: एक पूल में और दूसरा ढेर में। संदर्भ हीप में ऑब्जेक्ट को संदर्भित करेगा।


4

- मैं कैसे कर सकता हूं CaseInsensitiveString स्ट्रिंग की तरह व्यवहार करता है इसलिए उपरोक्त कथन ठीक है (स्ट्रिंग का विस्तार करने के साथ और w / बाहर)? यह स्ट्रिंग के बारे में क्या है जो इसे सिर्फ एक शाब्दिक रूप से पारित करने में सक्षम बनाता है? मेरी समझ से जावा सही में कोई "कॉपी कंस्ट्रक्टर" अवधारणा नहीं है?

पहले बिंदु से पर्याप्त कहा गया है। "पोलिश" एक स्ट्रिंग शाब्दिक है और CaseInsentiviveString वर्ग को नहीं सौंपा जा सकता है।

अब दूसरे बिंदु के बारे में

यद्यपि आप नए शब्द नहीं बना सकते हैं, आप "समान" दृष्टिकोण के लिए उस पुस्तक के पहले आइटम का अनुसरण कर सकते हैं, इसलिए निम्नलिखित कथन सत्य हैं:

    // Lets test the insensitiveness
    CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
    CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

    assert cis5 == cis6;
    assert cis5.equals(cis6);

यहाँ कोड है।

C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;

public final class CaseInsensitiveString  {


    private static final Map<String,CaseInsensitiveString> innerPool 
                                = new HashMap<String,CaseInsensitiveString>();

    private final String s;


    // Effective Java Item 1: Consider providing static factory methods instead of constructors
    public static CaseInsensitiveString valueOf( String s ) {

        if ( s == null ) {
            return null;
        }
        String value = s.toLowerCase();

        if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
             CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
         }

         return CaseInsensitiveString.innerPool.get( value );   
    }

    // Class constructor: This creates a new instance each time it is invoked.
    public CaseInsensitiveString(String s){
        if (s == null) {
            throw new NullPointerException();
         }         
         this.s = s.toLowerCase();
    }

    public boolean equals( Object other ) {
         if ( other instanceof CaseInsensitiveString ) {
              CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
             return this.s.equals( otherInstance.s );
         }

         return false;
    }


    public int hashCode(){
         return this.s.hashCode();
    }

// "जोर" कीवर्ड का उपयोग करके कक्षा का परीक्षण करें

    public static void main( String [] args ) {

        // Creating two different objects as in new String("Polish") == new String("Polish") is false
        CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
        CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");

        // references cis1 and cis2 points to differents objects.
        // so the following is true
        assert cis1 !=  cis2;      // Yes they're different
        assert cis1.equals(cis2);  // Yes they're equals thanks to the equals method

        // Now let's try the valueOf idiom
        CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
        CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");

        // References cis3 and cis4 points to same  object.
        // so the following is true
        assert cis3 == cis4;      // Yes they point to the same object
        assert cis3.equals(cis4); // and still equals.

        // Lets test the insensitiveness
        CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
        CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

        assert cis5 == cis6;
        assert cis5.equals(cis6);

        // Futhermore
        CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
        CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");

        assert cis8 == cis5 && cis7 == cis6;
        assert cis7.equals(cis5) && cis6.equals(cis8);
    }

}

C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java


C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString

C:\oreyes\samples\java\insensitive>

यही है, CaseInsensitiveString ऑब्जेक्ट्स का एक आंतरिक पूल बनाएं, और वहां से कॉरस्पॉन्डिंग उदाहरण को वापस करें।

इस तरह "==" ऑपरेटर एक ही मान का प्रतिनिधित्व करने वाली दो वस्तुओं के संदर्भ के लिए सही हो जाता है

यह उपयोगी है जब समान वस्तुओं का बहुत बार उपयोग किया जाता है और लागत पैदा करना महंगा होता है।

स्ट्रिंग क्लास प्रलेखन में कहा गया है कि वर्ग एक आंतरिक पूल का उपयोग करता है

वर्ग पूरा नहीं होता है, कुछ दिलचस्प मुद्दे उठते हैं जब हम चारसेंसेंस इंटरफ़ेस को लागू करने पर ऑब्जेक्ट की सामग्री को चलने की कोशिश करते हैं, लेकिन यह कोड यह दिखाने के लिए पर्याप्त है कि बुक में उस आइटम को कैसे लागू किया जा सकता है।

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

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

यह बूलियन वर्ग के लिए भी अच्छा काम करता है, क्योंकि केवल दो संभावित मूल्य हैं।

और आखिरकार यही कारण है कि क्लास इंटेगर में valueOf (int) , -128 से 127 int मान तक सीमित है।


3

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

हालाँकि, स्ट्रिंग शाब्दिक एक CaseInsensitiveString नहीं है, इसलिए आप अपने अंतिम उदाहरण में वह नहीं कर सकते जो आप चाहते हैं। इसके अलावा, C ++ में आप की तरह कास्टिंग ऑपरेटर को अधिभार करने का कोई तरीका नहीं है, इसलिए शाब्दिक रूप से कोई भी ऐसा तरीका नहीं है जो आप चाहते हैं। इसके बजाय आपको इसे अपने वर्ग के निर्माता के पैरामीटर के रूप में पास करना होगा। बेशक, मैं शायद String.toLowerCase () का उपयोग करूंगा और इसके साथ किया जाऊंगा।

साथ ही, आपके CaseInsensitiveString को CharSequence इंटरफ़ेस और साथ ही शायद Serializable और Comparable इंटरफेस को भी लागू करना चाहिए। बेशक, यदि आप तुलनीय लागू करते हैं, तो आपको बराबर () और हैशकोड () भी ओवरराइड करना चाहिए।


3

सिर्फ इसलिए कि आपके पास Stringअपनी कक्षा में शब्द है, इसका मतलब यह नहीं है कि आपको अंतर्निहित Stringवर्ग की सभी विशेष सुविधाएं मिलेंगी ।


3

CaseInsensitiveStringएक नहीं है String, हालांकि यह एक में शामिल है String। एक Stringशाब्दिक उदाहरण "उदाहरण" केवल एक को सौंपा जा सकता है String


2

CaseInsensitiveString और स्ट्रिंग अलग-अलग ऑब्जेक्ट हैं। आप ऐसा नहीं कर सकते:

CaseInsensitiveString cis = "Polish";

क्योंकि "पोलिश" एक स्ट्रिंग है, न कि CaseInsensitiveString। यदि स्ट्रिंग विस्तारित CaseInsensitiveString स्ट्रिंग है, तो आप ठीक होंगे, लेकिन जाहिर है कि यह नहीं है।

और यहां निर्माण के बारे में चिंता न करें, आप आवश्यक वस्तुएं नहीं बनाएंगे। यदि आप कंस्ट्रक्टर के कोड को देखते हैं, तो यह सब वह कर रहा है जो आपके द्वारा पारित स्ट्रिंग का संदर्भ संग्रहीत कर रहा है। कुछ भी अतिरिक्त नहीं बनाया जा रहा है।

स्ट्रिंग s = नया स्ट्रिंग ("फ़ॉबर") मामले में यह कुछ अलग कर रहा है। आप पहले शाब्दिक स्ट्रिंग "फोब्बर" बना रहे हैं, फिर उसमें से एक नया स्ट्रिंग बनाकर इसकी एक प्रति तैयार कर रहे हैं। उस प्रति को बनाने की कोई आवश्यकता नहीं है।


यहां तक ​​कि अगर आप स्ट्रिंग बढ़ाया यह काम नहीं करेगा। आपको CaseInsensitiveString को विस्तारित करने के लिए स्ट्रिंग की आवश्यकता होगी।
डार्रोन

या तो मामले में इसकी असंभव है, या तो क्योंकि स्ट्रिंग में बनाया गया है या क्योंकि इसकी घोषित अंतिम
ल्यूक

2

जब वे लिखने के लिए कहते हैं

String s = "Silly";

के बजाय

String s = new String("Silly");

इसका मतलब है कि वे एक स्ट्रिंग ऑब्जेक्ट बनाते हैं क्योंकि उपरोक्त दोनों कथन एक स्ट्रिंग ऑब्जेक्ट बनाते हैं लेकिन नया स्ट्रिंग () संस्करण दो स्ट्रिंग ऑब्जेक्ट बनाता है: एक ढेर में और दूसरा स्ट्रिंग निरंतर पूल में। इसलिए अधिक मेमोरी का उपयोग करना।

लेकिन जब आप लिखेंगे

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

आप एक स्ट्रिंग नहीं बना रहे हैं इसके बजाय आप क्लास CaseInsensitiveString का एक ऑब्जेक्ट बना रहे हैं। इसलिए आपको नए ऑपरेटर का उपयोग करने की आवश्यकता है।


1

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

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

इसका ठीक मतलब है, अगर दुभाषिया 3 देखता है तो इसे एक इंटर्जर ऑब्जेक्ट में बदल दिया जाएगा क्योंकि पूर्णांक इस तरह के शाब्दिक के लिए परिभाषित किया गया प्रकार है।

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

इसी तरह अगर दुभाषिया कुछ "" में देखता है तो इसे उसके डिफ़ॉल्ट प्रकार की वस्तु माना जाएगा। यह पृष्ठभूमि में काम करने वाला कुछ मूल कोड है।

MIT वीडियो व्याख्यान पाठ्यक्रम 6.00 के लिए धन्यवाद, जहां मुझे इस उत्तर के लिए संकेत मिला।


0

जावा में वाक्य रचना "पाठ" वर्ग java.lang.String का एक उदाहरण बनाता है। काम:

String foo = "text";

एक सरल काम है, जिसमें कोई कॉपी कंस्ट्रक्टर आवश्यक नहीं है।

MyString bar = "text";

जो कुछ भी आप करते हैं वह अवैध है क्योंकि MyString वर्ग java.lang.String या java.lang.String का सुपरक्लास नहीं है।


0

सबसे पहले, आप एक वर्ग नहीं बना सकते हैं जो स्ट्रिंग से फैली हुई है, क्योंकि स्ट्रिंग एक अंतिम वर्ग है। और जावा स्ट्रिंग्स को अन्य वर्गों से अलग तरीके से प्रबंधित करता है ताकि केवल स्ट्रिंग के साथ ही आप कर सकें

String s = "Polish";

लेकिन अपनी कक्षा को सफेद करें आपको निर्माणकर्ता को आमंत्रित करना होगा। तो, वह कोड ठीक है।


0

मैं सिर्फ इतना जोड़ूंगा कि जावा में कॉपी कंस्ट्रक्टर हैं ...

ठीक है, यह तर्क के रूप में एक ही प्रकार की वस्तु के साथ एक साधारण निर्माता है।


2
यह एक डिज़ाइन पैटर्न है, न कि भाषा निर्माण। जावा के साथ बहुत कम उपयोग हैं जहां एक कॉपी कंस्ट्रक्टर दिलचस्प होगा क्योंकि सब कुछ हमेशा "संदर्भ द्वारा" होता है, और प्रत्येक ऑब्जेक्ट में केवल एक कॉपी होती है। वास्तव में, प्रतियाँ बनाने से वास्तव में बहुत सारी समस्याएँ पैदा होंगी।
बिल के

0

JDK के अधिकांश संस्करणों में दो संस्करण समान होंगे:

स्ट्रिंग s = नया स्ट्रिंग ("मूर्खतापूर्ण");

स्ट्रिंग s = "अब मूर्ख नहीं";

क्योंकि तार अपरिवर्तनीय हैं, संकलक स्ट्रिंग स्थिरांक की एक सूची रखता है और यदि आप एक नया बनाने की कोशिश करते हैं, तो पहले यह देखने के लिए जांचें कि क्या स्ट्रिंग पहले से परिभाषित है। यदि यह है तो मौजूदा अपरिवर्तनीय स्ट्रिंग का संदर्भ दिया जाता है।

स्पष्ट करने के लिए - जब आप "स्ट्रिंग s =" कहते हैं, तो आप एक नए चर को परिभाषित कर रहे हैं, जो स्टैक पर जगह लेता है - फिर आप चाहे "अब मूर्खतापूर्ण नहीं" या नए स्ट्रिंग ("मूर्खतापूर्ण") बिल्कुल एक ही बात होती है - एक नया निरंतर स्ट्रिंग आपके आवेदन और संदर्भ बिंदुओं में संकलित है।

मैं यहाँ भेद नहीं देखता। हालांकि आपके अपने वर्ग के लिए, जो अपरिवर्तनीय नहीं है, यह व्यवहार अप्रासंगिक है और आपको अपने निर्माता को कॉल करना होगा।

अद्यतन: मैं गलत था! डाउन वोट और टिप्पणी के आधार पर मैंने यह परीक्षण किया और महसूस किया कि मेरी समझ गलत है - नया स्ट्रिंग ("मूर्खतापूर्ण") वास्तव में मौजूदा के पुन: उपयोग के बजाय एक नया स्ट्रिंग बनाता है। मैं स्पष्ट नहीं हूं कि ऐसा क्यों होगा (इससे क्या लाभ होगा?) लेकिन कोड शब्दों की तुलना में जोर से बोलता है!


0

स्ट्रिंग उन विशेष वर्गों में से एक है, जिसमें आप उन्हें नए श्रृंग भाग के बिना बना सकते हैं

यह वैसा ही है

int x = y;

या

चार सी;


0

यह एक बुनियादी कानून है कि स्ट्रिंग्स इन जावा अपरिवर्तनीय और मामला संवेदनशील है।


0
 String str1 = "foo"; 
 String str2 = "foo"; 

Str1 और str2 दोनों का संबंध एक ही स्ट्रिंग ऑब्जेक्ट, "foo" से है, b'coz Java StringPool में स्ट्रिंग्स का प्रबंधन करता है, इसलिए यदि एक नया वेरिएबल उसी स्ट्रिंग को संदर्भित करता है, तो यह एक और बनाता नहीं है, बल्कि एक ही स्ट्रिंग StringPool में मौजूद है ।

 String str1 = new String("foo"); 
 String str2 = new String("foo");

यहाँ str1 और str2 दोनों अलग-अलग ऑब्जेक्ट्स से संबंधित हैं, b'coz new String () जबरदस्ती एक नया स्ट्रिंग ऑब्जेक्ट बनाते हैं।


-1

जावा आपके द्वारा अपने कोड में उपयोग किए जाने वाले प्रत्येक स्ट्रिंग शाब्दिक के लिए एक स्ट्रिंग ऑब्जेक्ट बनाता है। किसी भी समय ""उपयोग किया जाता है, यह कॉलिंग के समान है new String()

स्ट्रिंग्स जटिल डेटा होते हैं जो आदिम डेटा की तरह "कार्य" करते हैं। स्ट्रिंग शाब्दिक वास्तव में ऑब्जेक्ट हैं भले ही हम दिखाते हैं कि वे आदिम शाब्दिक हैं, जैसे 6, 6.0, 'c',आदि। इसलिए स्ट्रिंग "शाब्दिक" "text"मूल्य के साथ एक नया स्ट्रिंग ऑब्जेक्ट देता है char[] value = {'t','e','x','t}। इसलिए, बुला रहा है

new String("text"); 

वास्तव में कॉल करने के लिए समान है

new String(new String(new char[]{'t','e','x','t'}));

उम्मीद है कि यहाँ से, आप देख सकते हैं कि आपकी पाठ्यपुस्तक इस अतिरेक को क्यों मानती है।

संदर्भ के लिए, यहाँ स्ट्रिंग का कार्यान्वयन है: http://www.docjar.com/html/api/java/lang/String.jpg.html

यह एक मजेदार रीड है और कुछ अंतर्दृष्टि को प्रेरित कर सकता है। यह शुरुआती लोगों को पढ़ने और समझने की कोशिश करने के लिए भी बहुत अच्छा है, क्योंकि कोड बहुत ही पेशेवर और सम्मेलन-अनुरूप कोड प्रदर्शित करता है।

एक और अच्छा संदर्भ स्ट्रिंग्स पर जावा ट्यूटोरियल है: http://docs.oracle.com/javase/tutorial/java/data/usings.html


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