अपरिवर्तनीय से क्या अभिप्राय है?


400

यह कभी भी पूछा जाने वाला सबसे कठिन सवाल हो सकता है लेकिन मुझे लगता है कि यह एक जावा नौसिखिया के लिए काफी भ्रामक है।

  1. क्या कोई स्पष्ट कर सकता है कि अपरिवर्तनीय का क्या अर्थ है ?
  2. Stringअपरिवर्तनीय क्यों है ?
  3. अपरिवर्तनीय वस्तुओं के क्या फायदे / नुकसान हैं?
  4. एक उत्परिवर्तित वस्तु जैसे StringBuilderस्ट्रिंग और उप-पद्य को क्यों पसंद किया जाना चाहिए ?

एक अच्छा उदाहरण (जावा में) वास्तव में सराहना की जाएगी।


73
देखिए, यह इतना गूंगा सवाल नहीं था। खुशी है कि आपने पूछा!
DOK

2
वैसे, मुझे नहीं लगता कि यह कभी सबसे कठिन सवाल है :) मुझे लगता है कि यह समझने के लिए एक बहुत ही महत्वपूर्ण अवधारणा है
जेसन कोको

1
जब आपने StringBuilder कहा, तो क्या आपका मतलब उत्परिवर्ती वर्ग StringBuffer नहीं था? स्ट्रिंग और स्ट्रिंगर की तुलना में स्ट्रिंग और स्ट्रिंगरफ़र फ़ंक्शन के समान हैं। StringBuffer प्रभावी रूप से एक परिवर्तनशील स्ट्रिंग है।
डेरेक महार १५

3
क्या मुझे सुझाव है कि हम इस प्रश्न को "शुरुआती" टैग जोड़ते हैं ताकि जावा के नए प्रोग्रामर इसे अन्य परिचय प्रश्नों की खोज में खोज सकें?
डेरेक महार

जवाबों:


268

अपरिवर्तनीय का मतलब है कि एक बार किसी ऑब्जेक्ट के लिए कंस्ट्रक्टर ने निष्पादन पूरा कर लिया है कि उदाहरण को बदला नहीं जा सकता है।

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

जैसे

class Foo
{
     private final String myvar;

     public Foo(final String initialValue)
     {
         this.myvar = initialValue;
     }

     public String getValue()
     {
         return this.myvar;
     }
}

Fooचिंता करने की ज़रूरत नहीं है कि कॉलर getValue()स्ट्रिंग में पाठ को बदल सकता है।

आप के लिए एक समान वर्ग की कल्पना तो Fooहै, लेकिन एक साथ StringBuilderनहीं बल्कि एक से Stringएक सदस्य के रूप में आप देख सकते हैं करने के लिए है कि एक फोन करने वाले getValue()को बदलने के लिए सक्षम हो जाएगा StringBuilderएक की विशेषता Fooउदाहरण।

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


3
मुझे लगता है कि आपको कम से कम एक बार मान असाइन करने के लिए एक arg कंस्ट्रक्टर को जोड़ना चाहिए। वर्तमान कोड की बात स्पष्ट नहीं है क्योंकि वास्तव में बदलने का कोई मूल्य नहीं है :)।
गॉर्जियस बोल्युबा

4
आपको फ़ील्ड को आसानी से बनाना चाहिए। यह पूरी तरह से स्पष्ट करता है कि क्षेत्र अपरिवर्तनीय है। अभी यह सम्मेलन द्वारा अपरिवर्तनीय है
JaredPar

7
वास्तव में अपरिवर्तनीय होने के लिए सदस्य MyVar को अंतिम होना चाहिए।
laz

13
आप सही हैं कि MyVar फू के बाहर सुलभ नहीं है। हालाँकि, अंतिम की उपस्थिति किसी को भी इंगित करती है जो भविष्य में वर्ग को संशोधित कर सकता है कि इसका मूल्य बदलने के लिए नहीं है। मैं ऐसी परिस्थितियों में यथासंभव स्पष्ट होने का पक्ष लेता हूं।
लाज़

2
कैसे के बारे में "संदर्भ प्रकार केवल अंतिम कीवर्ड का उपयोग करके अपरिवर्तनीय नहीं बनाया जा सकता है। अंतिम केवल पुनर्मूल्यांकन को रोकता है।" से en.wikipedia.org/wiki/Immutable_object
Yousha Aleayoub

81

एक अपरिवर्तनीय वस्तु एक ऐसी वस्तु है जहां आंतरिक क्षेत्र (या कम से कम, सभी आंतरिक क्षेत्र जो इसके बाहरी व्यवहार को प्रभावित करते हैं) को बदला नहीं जा सकता है।

अपरिवर्तनीय स्ट्रिंग्स के बहुत सारे फायदे हैं:

प्रदर्शन: निम्नलिखित कार्रवाई करें:

String substring = fullstring.substring(x,y);

प्रतिस्थापन () विधि के लिए अंतर्निहित सी शायद कुछ इस तरह है:

// Assume string is stored like this:
struct String { char* characters; unsigned int length; };

// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
    struct String* out = malloc(sizeof(struct String));
    out->characters = in->characters + begin;
    out->length = end - begin;
    return out;
}

ध्यान दें कि किसी भी वर्ण को कॉपी नहीं करना है! यदि स्ट्रिंग ऑब्जेक्ट उत्परिवर्तनीय था (वर्ण बाद में बदल सकते हैं) तो आपको सभी वर्णों को कॉपी करना होगा, अन्यथा प्रतिस्थापन में वर्णों में परिवर्तन बाद में अन्य स्ट्रिंग में परिलक्षित होगा।

Concurrency: यदि किसी अपरिवर्तनीय वस्तु की आंतरिक संरचना वैध है, तो यह हमेशा मान्य होगी। इस बात की कोई संभावना नहीं है कि विभिन्न धागे उस वस्तु के भीतर एक अमान्य स्थिति बना सकते हैं। इसलिए, अपरिवर्तनीय वस्तुएं थ्रेड सेफ हैं

कचरा संग्रह: कचरा संग्रहकर्ता के लिए अपरिवर्तनीय वस्तुओं के बारे में तार्किक निर्णय लेना बहुत आसान है।

हालांकि, वहाँ भी अपरिवर्तनीयता के लिए नीचे हैं:

प्रदर्शन: रुको, मैंने सोचा था कि आपने कहा कि प्रदर्शन अपरिवर्तनीयता का एक उल्टा था! खैर, यह कभी-कभी होता है, लेकिन हमेशा नहीं। निम्नलिखित कोड लें:

foo = foo.substring(0,4) + "a" + foo.substring(5);  // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder

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

struct String* concatenate(struct String* first, struct String* second)
{
    struct String* new = malloc(sizeof(struct String));
    new->length = first->length + second->length;

    new->characters = malloc(new->length);

    int i;

    for(i = 0; i < first->length; i++)
        new->characters[i] = first->characters[i];

    for(; i - first->length < second->length; i++)
        new->characters[i] = second->characters[i - first->length];

    return new;
}

// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));

ध्यान दें कि समवर्ती को दो बार कहा जाता है जिसका अर्थ है कि पूरे स्ट्रिंग को लूप किया जाना है! इसके लिए C कोड से तुलना करेंbarऑपरेशन :

bar->characters[4] = 'a';

उत्परिवर्ती स्ट्रिंग ऑपरेशन स्पष्ट रूप से बहुत तेज है।

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

// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
    StringBuilder mutable;
    boolean first = true;

    for(int i = 0; i < strings.length; i++)
    {
        if(!first) first = false;
        else mutable.append(separator);

        mutable.append(strings[i]);
    }

    return mutable.toString();
}

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


4
बहुत अच्छा पढ़ा! सिर्फ एक बात मुझे लगता है कि यह होना चाहिए (पहले) और नहीं तो (पहले!)
सिद्धार्थ २

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

7
Passing pointers because Java is pass-by-referenceजावा "पास-बाय-वैल्यू नहीं है?"
क्रिस्टियान गुटू

@CristianGutu हाँ आप सही हैं JAVA "पास बाय वैल्यू" नहीं "पास बाय REFERENCE"
अर्श कौशल

संदर्भ मान के रूप में पारित किया गया है !!
देव

31

यदि आप ऊपर बताई गई विकिपीडिया परिभाषा का उपयोग करते हैं, तो स्ट्रिंग अपरिवर्तनीय नहीं है।

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

तो शायद अपरिवर्तनीय की परिभाषा एक ऐसी वस्तु होनी चाहिए जिसे परिवर्तित होने के लिए नहीं देखा जा सकता है।

अगर राज्य बनने के बाद एक अपरिवर्तनीय वस्तु में बदल जाता है, लेकिन कोई भी इसे नहीं देख सकता है (प्रतिबिंब के बिना) क्या वस्तु अभी भी अपरिवर्तनीय है?


1
अच्छा विचार - एक ऐसी वस्तु जिसे परिवर्तित नहीं किया जा सकता है, साथ ही बाहर से इसे बदलने का कोई तरीका नहीं है। हैशकोड () के लिए निजी क्षेत्र एक आंतरिक परिवर्तन है जो वस्तु के बाहरी दृश्यमान स्थिति के लिए भौतिक नहीं है।
मपराज

2
यदि आप प्रतिबिंब का उपयोग करते हैं तो वास्तव में इसे बदला जा सकता है। यदि आप परावर्तन की अनुमति देते हैं तो सेडगेविक के स्ट्रिंग्स परस्पर अधिक हैं
मिगेल

24

अपरिवर्तनीय वस्तुएँ ऐसी वस्तुएँ हैं जिन्हें प्रोग्रामेटिक रूप से परिवर्तित नहीं किया जा सकता है। वे विशेष रूप से बहु-थ्रेडेड वातावरण या अन्य वातावरण के लिए अच्छे हैं जहां एक से अधिक प्रक्रिया किसी ऑब्जेक्ट में मानों को बदलने (म्यूट) करने में सक्षम है।

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

उदाहरण के लिए, मान लें कि मेरे पास ColoredString नामक एक वर्ग है जिसका स्ट्रिंग मूल्य और एक स्ट्रिंग रंग है:

public class ColoredString {

    private String color;
    private String string;

    public ColoredString(String color, String string) {
        this.color  = color;
        this.string = string;
    }

    public String getColor()  { return this.color;  }
    public String getString() { return this.string; }

    public void setColor(String newColor) {
        this.color = newColor;
    }

}

इस उदाहरण में, ColoredString को उत्परिवर्तित कहा जाता है क्योंकि आप एक नया ColoredString वर्ग बनाए बिना इसके प्रमुख गुणों में से एक को बदल सकते हैं (उत्परिवर्तित)। उदाहरण के लिए, यह खराब हो सकता है, उदाहरण के लिए, मान लें कि आपके पास एक GUI एप्लिकेशन है जिसमें कई थ्रेड हैं और आप विंडो में डेटा प्रिंट करने के लिए ColoredStrings का उपयोग कर रहे हैं। यदि आपके पास ColoredString का एक उदाहरण है, जिसे बनाया गया था

new ColoredString("Blue", "This is a blue string!");

फिर आप स्ट्रिंग को हमेशा "ब्लू" होने की उम्मीद करेंगे। हालांकि, एक और सूत्र को इस उदाहरण का आभास हुआ और उसने फोन किया

blueString.setColor("Red");

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

जावा में पुनर्कथन करने के लिए java.lang.String एक अपरिवर्तनीय वस्तु है (इसे एक बार बनाने के बाद इसे बदला नहीं जा सकता है) और java.lang.StringBuilder एक उत्परिवर्तित वस्तु है क्योंकि इसे एक नया उदाहरण बनाए बिना बदला जा सकता है।


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

@JaredPar - वास्तव में, क्लास बिल्कुल भी अपरिवर्तनीय नहीं है ... यह प्रदर्शित करने के लिए एक परिवर्तनशील वर्ग का एक उदाहरण है कि यह एक मुद्दा क्यों हो सकता है।
जेसन कोको

1
@JaredPar - ओह, यह पूरी तरह से ठीक है :) मैं इसे और अधिक स्पष्ट होने के लिए इसे फिर से लिखने जा रहा था, लेकिन डगलस पहले से ही अच्छी तरह से लिखा गया है और पसंदीदा लगता है, इसलिए मैं सिर्फ एक और उदाहरण के रूप में मेरा पीछा छोड़ दूंगा; लेकिन किसी ने वास्तव में संपत्तियों को अंतिम बनाने के लिए इसे संपादित किया जो मुझे लगा कि वह मनोरंजक था :)
जेसन कोको

24
  1. बड़े अनुप्रयोगों में स्मृति के बड़े बिट्स पर कब्जा करने के लिए स्ट्रिंग शाब्दिक के लिए इसका आम तो स्मृति को कुशलतापूर्वक संभालने के लिए, JVM "स्ट्रिंग स्थिर पूल" नामक एक क्षेत्र आवंटित करता है। ( ध्यान दें कि स्मृति में भी एक अपरिवर्तित स्ट्रिंग एक चार [] के आसपास वहन करती है, इसकी लंबाई के लिए एक और इसके हैशटैड के लिए एक नंबर के लिए)। , इसके विपरीत, अधिकतम आठ तत्काल बाइट्स की आवश्यकता होती है )
  2. जब एक स्ट्रिंग शाब्दिक भर में आता है, तो यह देखने के लिए कि क्या एक समान शाब्दिक पहले से मौजूद है, पूल की जाँच करता है। और यदि कोई पाया जाता है, तो नए शाब्दिक का संदर्भ मौजूदा स्ट्रिंग को निर्देशित किया जाता है, और कोई नया 'स्ट्रिंग शाब्दिक ऑब्जेक्ट' नहीं बनाया जाता है (मौजूदा स्ट्रिंग को बस एक अतिरिक्त संदर्भ मिलता है)।
  3. इसलिए ... स्ट्रिंग उत्परिवर्तन स्मृति को बचाता है ...
  4. लेकिन जब कोई भी चर मूल्य बदलता है, तो वास्तव में - यह केवल उनका संदर्भ होता है, न कि स्मृति में मूल्य (इसलिए यह इसे संदर्भित अन्य चर को प्रभावित नहीं करेगा) जैसा कि नीचे देखा गया है ...।

स्ट्रिंग s1 = "पुरानी स्ट्रिंग";

//s1 variable, refers to string in memory
        reference                 |     MEMORY       |
        variables                 |                  |

           [s1]   --------------->|   "Old String"   |

स्ट्रिंग s2 = s1;

//s2 refers to same string as s1
                                  |                  |
           [s1]   --------------->|   "Old String"   |
           [s2]   ------------------------^

s1 = "न्यू स्ट्रिंग";

//s1 deletes reference to old string and points to the newly created one
           [s1]   -----|--------->|   "New String"   |
                       |          |                  |
                       |~~~~~~~~~X|   "Old String"   |
           [s2]   ------------------------^

मूल स्ट्रिंग 'मेमोरी' में परिवर्तन नहीं हुआ, लेकिन संदर्भ चर को बदल दिया गया ताकि यह नए स्ट्रिंग को संदर्भित करे। और अगर हमारे पास s2 नहीं है, तो "ओल्ड स्ट्रिंग" अभी भी मेमोरी में होगा लेकिन हम इसे एक्सेस नहीं कर पाएंगे ...


16

"अपरिवर्तनीय" का अर्थ है कि आप मूल्य नहीं बदल सकते। यदि आपके पास स्ट्रिंग क्लास का एक उदाहरण है, तो आपके द्वारा कॉल की गई कोई भी विधि जो मूल्य को संशोधित करती है, वास्तव में एक और स्ट्रिंग का निर्माण करेगी।

String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"

परिवर्तनों को संरक्षित करने के लिए आपको कुछ ऐसा करना चाहिए जैसे कि foo = foo.sustring (3);

संग्रह के साथ काम करने पर अपरिवर्तनीय बनाम उत्परिवर्तनीय मजाकिया हो सकता है। इस बारे में सोचें कि क्या होगा यदि आप मानचित्र के लिए एक कुंजी के रूप में उत्परिवर्तित वस्तु का उपयोग करते हैं और फिर मूल्य (टिप: विचार करें equalsऔर hashCode) बदल दें।


13

java.time

थोड़ी देर हो सकती है लेकिन यह समझने के लिए कि एक अपरिवर्तनीय वस्तु क्या है, नए जावा 8 दिनांक और समय एपीआई ( java.time ) से निम्न उदाहरण पर विचार करें । जैसा कि आप शायद जानते हैं कि जावा 8 से सभी दिनांक ऑब्जेक्ट निम्न उदाहरण में अपरिवर्तनीय हैं

LocalDate date = LocalDate.of(2014, 3, 18); 
date.plusYears(2);
System.out.println(date);

आउटपुट:

2014-03-18

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

तो, उस कोड उदाहरण को नई वस्तु को तुरंत पकड़ना चाहिए और उसका उपयोग करना चाहिए और उस कॉल से वापस लौटना चाहिए plusYears

LocalDate date = LocalDate.of(2014, 3, 18); 
LocalDate dateAfterTwoYears = date.plusYears(2);

date.toString ()… 2014-03-18

dateAfterTwoYears.toString ()… 2016-03-18


8

मुझे वास्तव में जावा 5 स्टडी गाइड के लिए SCJP सन सर्टिफाइड प्रोग्रामर से स्पष्टीकरण पसंद है ।

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


यह किसी भी समान अपरिवर्तनीय वस्तुओं के साथ ऐसा करने में सक्षम होना चाहिए, लेकिन मुझे लगता है कि बहुत अधिक रनटाइम लगेगा।
Zan Lynx 3

8

जो वस्तुएं अपरिवर्तनीय हैं, उनका निर्माण होने के बाद उनकी स्थिति नहीं बदल सकती है।

जब भी आप कर सकते हैं अपरिवर्तनीय वस्तुओं का उपयोग करने के तीन मुख्य कारण हैं, जिनमें से सभी आपके कोड में आपके द्वारा प्रस्तुत की जाने वाली कीड़े की संख्या को कम करने में मदद करेंगे:

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

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


5

एक अर्थ यह है कि कंप्यूटर में मूल्य को कैसे संग्रहीत किया जाता है, उदाहरण के लिए .Net स्ट्रिंग के लिए, इसका मतलब है कि मेमोरी में स्ट्रिंग को बदला नहीं जा सकता है, जब आप सोचते हैं कि आप इसे बदल रहे हैं, तो आप वास्तव में एक नया निर्माण कर रहे हैं स्मृति में स्ट्रिंग और मौजूदा चर की ओर इशारा करते हुए (जो कि पात्रों के वास्तविक संग्रह के लिए सिर्फ एक संकेतक है) नए स्ट्रिंग के लिए।


4
String s1="Hi";
String s2=s1;
s1="Bye";

System.out.println(s2); //Hi  (if String was mutable output would be: Bye)
System.out.println(s1); //Bye

s1="Hi" : एक वस्तु s1 इसमें "हाय" मान के साथ बनाया गया था।

s2=s1 : s2s1 ऑब्जेक्ट के संदर्भ में एक ऑब्जेक्ट बनाया जाता है।

s1="Bye": पिछले s1ऑब्जेक्ट का मान नहीं बदलता है क्योंकि s1स्ट्रिंग प्रकार और स्ट्रिंग प्रकार एक अपरिवर्तनीय प्रकार है, इसके बजाय कंपाइलर "बाय" मान के साथ एक नई स्ट्रिंग ऑब्जेक्ट बनाते हैं और s1इसे संदर्भित करते हैं। यहां जब हम s2मूल्य प्रिंट करते हैं , तो परिणाम "हाय" नहीं "बाय" होगा क्योंकि s2पिछली s1वस्तु का संदर्भ दिया गया था जिसमें "हाय" मान था।


क्या आप कृपया थोड़ा स्पष्टीकरण जोड़ सकते हैं?
माइनिगेक

3

अपरिवर्तनीय का अर्थ है कि एक बार जब वस्तु बनाई जाती है, तो उसके गैर-सदस्य बदल जाएंगे। Stringअपरिवर्तनीय है क्योंकि आप इसकी सामग्री नहीं बदल सकते। उदाहरण के लिए:

String s1 = "  abc  ";
String s2 = s1.trim();

उपरोक्त कोड में, स्ट्रिंग s1 नहीं बदला, एक अन्य ऑब्जेक्ट ( s2) का उपयोग करके बनाया गया था s1


3

अपरिवर्तनीय का तात्पर्य अपरिवर्तनीय या अपरिवर्तनीय है। एक बार स्ट्रिंग ऑब्जेक्ट बन जाने के बाद उसका डेटा या स्टेट नहीं बदला जा सकता है

Bellow उदाहरण पर विचार करें,

class Testimmutablestring{  
  public static void main(String args[]){  
    String s="Future";  
    s.concat(" World");//concat() method appends the string at the end  
    System.out.println(s);//will print Future because strings are immutable objects  
  }  
 }  

आइए विचार करें bellow आरेख पर विचार करें,

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

इस आरेख में, आप "फ्यूचर वर्ल्ड" के रूप में बनाई गई नई वस्तु देख सकते हैं। लेकिन "भविष्य" नहीं बदलते। Because String is immutables, फिर भी "फ्यूचर" का संदर्भ लें। यदि आपको "फ्यूचर वर्ल्ड" कॉल करने की आवश्यकता है,

String s="Future";  
s=s.concat(" World");  
System.out.println(s);//print Future World

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

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


2

एक बार अस्थिर होने के बाद, परिवर्तित नहीं किया जा सकता है। एक वर्ग पर विचार करें कि हैशटेबल या समान के लिए कुंजी के रूप में एक उदाहरण का उपयोग किया जा सकता है। जावा सर्वोत्तम प्रथाओं की जाँच करें।


0

अपरिवर्तनीय वस्तुएँ

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

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

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

निम्नलिखित उपवर्ग एक ऐसा वर्ग लेते हैं, जिसके उदाहरण उत्परिवर्तनीय होते हैं और एक वर्ग को इसके उदाहरणों से अपरिवर्तनीय उदाहरण देते हैं। ऐसा करने में, वे इस तरह के रूपांतरण के लिए सामान्य नियम देते हैं और अपरिवर्तनीय वस्तुओं के कुछ फायदे प्रदर्शित करते हैं।

स्रोत


0

जैसा कि स्वीकार किया गया जवाब सभी सवालों के जवाब नहीं देता है। मैं 11 साल और 6 महीने के बाद जवाब देने के लिए मजबूर हूं।

क्या कोई स्पष्ट कर सकता है कि अपरिवर्तनीय का क्या अर्थ है?

आशा है कि आपका मतलब अपरिवर्तनीय वस्तु है (क्योंकि हम अपरिवर्तनीय संदर्भ के बारे में सोच सकते हैं )।

एक ऑब्जेक्ट अपरिवर्तनीय है : यदि एक बार बनाया गया है, तो वे हमेशा एक ही मूल्य का प्रतिनिधित्व करते हैं (कोई भी विधि नहीं है जो मूल्य को बदलते हैं)।

Stringअपरिवर्तनीय क्यों है ?

उपरोक्त परिभाषा का सम्मान करें जिसे Sting.java स्रोत कोड को देखकर जांचा जा सकता है ।

अपरिवर्तनीय वस्तुओं के क्या फायदे / नुकसान हैं? अपरिवर्तनीय प्रकार हैं:

  • कीड़े से सुरक्षित।

  • समझने में आसान है।

  • और अधिक परिवर्तन के लिए तैयार है।

StringBuilder जैसे एक उत्परिवर्तनीय वस्तु को स्ट्रिंग और उप-पद्य पर क्यों पसंद किया जाना चाहिए?

प्रश्न को तोड़ना हमें प्रोग्रामिंग में म्यूटेबल स्ट्रिंगबर्ल की आवश्यकता क्यों है? इसके लिए एक आम उपयोग इस तरह से एक साथ बड़ी संख्या में तारों को समतल करना है:

String s = "";
for (int i = 0; i < n; ++i) {
    s = s + n;
}

अपरिवर्तनीय तारों का उपयोग करते हुए, यह बहुत सारी अस्थायी प्रतियां बनाता है - स्ट्रिंग की पहली संख्या ("0") वास्तव में n को अंतिम स्ट्रिंग के निर्माण के समय में कॉपी किया जाता है, दूसरी संख्या को एन -1 बार कॉपी किया जाता है, और इसी तरह पर। यह वास्तव में केवल नकल करने वाले सभी तत्वों को करने के लिए ओ (एन 2) समय का खर्च करता है, भले ही हम केवल एन तत्वों को मिलाते हैं।

StringBuilder को इस प्रतिलिपि को कम करने के लिए डिज़ाइन किया गया है। यह बहुत ही अंत तक किसी भी नकल करने से बचने के लिए एक सरल लेकिन चतुर आंतरिक डेटा संरचना का उपयोग करता है, जब आप अंतिम स्ट्रिंग के लिए एक toString () कॉल के साथ पूछते हैं:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
  sb.append(String.valueOf(n));
}
String s = sb.toString();

अच्छा प्रदर्शन प्राप्त करना एक कारण है कि हम परस्पर वस्तुओं का उपयोग क्यों करते हैं। एक और सुविधाजनक साझाकरण है: आपके प्रोग्राम के दो भाग एक सामान्य परिवर्तनशील डेटा संरचना साझा करके अधिक आसानी से संचार कर सकते हैं।

यहाँ और अधिक पाया जा सकता है: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types


-1

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

विज्ञापन प्रोग्रामिंग भाषा, जो तेजी से लोकप्रिय हो जाती है, "अपरिवर्तनीय" कीवर्ड के माध्यम से "अपरिवर्तनीयता" की धारणा है। इसके बारे में डॉ। डॉब के लेख की जाँच करें - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 । यह समस्या को पूरी तरह से समझाता है।


मुझे विश्वास है कि डी 2.020 के रूप में कीवर्ड को अपरिवर्तनीय से अपरिवर्तनीय में बदल दिया गया था। मैं एक बिंदु नहीं देखता, लेकिन यह कहता है, "अपरिवर्तनीय अब लागू हो गया है।" digitalmars.com/d/2.0/changelog.html#new2_020
he_the_great
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.