अंतिम वस्तु को संशोधित क्यों किया जा सकता है?


89

मैं एक कोड आधार पर निम्नलिखित कोड पर आया हूं जिस पर मैं काम कर रहा हूं:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }

    public static void addProvider(ConfigurationProvider provider) {
        INSTANCE.providers.add(provider);
    }

    ...

INSTANCEके रूप में घोषित किया गया है final। वस्तुओं को क्यों जोड़ा जा सकता है INSTANCE? अंतिम के उपयोग को अमान्य नहीं करना चाहिए। (यह नहीं है)।

मैं मान रहा हूं कि उत्तर को संकेत और स्मृति के साथ कुछ करना है, लेकिन यह सुनिश्चित करना चाहते हैं।


यह गलत धारणा बहुत बार सामने आती है, जरूरी नहीं कि एक सवाल के रूप में। अक्सर एक उत्तर या टिप्पणी के रूप में।
रॉबिन

5
जेएलएस से सरल व्याख्या: "यदि अंतिम चर किसी वस्तु का संदर्भ रखता है, तो वस्तु पर परिचालन द्वारा वस्तु की स्थिति को बदला जा सकता है, लेकिन चर हमेशा एक ही वस्तु को संदर्भित करेगा।" JLS प्रलेखन
realPK

जवाबों:


161

finalबस वस्तु संदर्भ को अपरिवर्तनीय बनाता है । यह जिस वस्तु को इंगित करता है वह ऐसा करने से अपरिवर्तनीय नहीं है। INSTANCEकभी भी किसी अन्य वस्तु को संदर्भित नहीं कर सकता है, लेकिन जिस वस्तु को संदर्भित करता है वह राज्य को बदल सकता है।


1
+1, अधिक जानकारी के लिए java.sun.com/docs/books/jls/second_edition/html/… , खंड 4.5.4 देखें।
हाबिल मोरेलोस

तो चलिए कहते हैं कि मैं एक ConfigurationServiceवस्तु को डिसेर्बलाइज करता हूं और मैं एक INSTANCE करने की कोशिश करता हूं = deserializedConfigurationServiceअनुमति नहीं दी जाएगी?
डाईगोएगिलर

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

@AkhilGite ने आपके उत्तर को संपादित करने को गलत बना दिया; इसने वास्तव में वाक्य के अर्थ को उलट दिया, जो सही था। संदर्भ अपरिवर्तनीय है। वस्तु परस्पर बनी रहती है। यह "अपरिवर्तनीय नहीं" हो जाता है।
शॉन ओवेन

@ SeanOwen Sry मैंने किया संपादन के लिए, आपका कथन पूरी तरह से सही है और धन्यवाद।
अखिलगीत

33

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

final != immutable

finalकीवर्ड यकीन संदर्भ बदल नहीं है बनाने के लिए प्रयोग किया जाता है (यह है कि, संदर्भ यह एक नया एक के साथ प्रतिस्थापित नहीं किया जा सकता है)

लेकिन, यदि विशेषता स्व है, तो यह परिवर्तन योग्य है कि आपने अभी जो वर्णन किया है वह करना ठीक है।

उदाहरण के लिए

class SomeHighLevelClass {
    public final MutableObject someFinalObject = new MutableObject();
}

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

तो यह संभव नहीं है:

....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor  = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final

लेकिन अगर यह स्वयं वस्तु इस तरह परस्पर है:

class MutableObject {
     private int n = 0;

     public void incrementNumber() {
         n++;
     }
     public String toString(){
         return ""+n;
     }
}  

फिर, उस परिवर्तनशील वस्तु द्वारा निहित मूल्य को बदला जा सकता है।

SomeHighLevelClass someObject = new SomeHighLevelClass();

someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();

System.out.println( someObject.someFinal ); // prints 3

इसका एक ही प्रभाव है कि आपकी पोस्ट:

public static void addProvider(ConfigurationProvider provider) {
    INSTANCE.providers.add(provider);
}

यहां आप INSTANCE का मूल्य नहीं बदल रहे हैं, आप इसकी आंतरिक स्थिति को संशोधित कर रहे हैं (के माध्यम से, प्रदाता। विधि)

यदि आप यह रोकना चाहते हैं कि कक्षा की परिभाषा को इस तरह बदला जाना चाहिए:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }
    // Avoid modifications      
    //public static void addProvider(ConfigurationProvider provider) {
    //    INSTANCE.providers.add(provider);
    //}
    // No mutators allowed anymore :) 
....

लेकिन, यह बहुत मतलब नहीं हो सकता है :)

वैसे, आपको मूल रूप से उसी कारण से उस तक पहुंच को सिंक्रनाइज़ करना होगा


26

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

हमेशा याद रखें कि जब आप एक संदर्भ प्रकार चर घोषित करते हैं, तो उस चर का मूल्य एक संदर्भ होता है, वस्तु नहीं।


11

अंतिम का अर्थ है कि संदर्भ को बदला नहीं जा सकता। यदि इसे अंतिम घोषित किया जाता है, तो आप किसी अन्य संदर्भ में पुन: असाइन नहीं कर सकते। वस्तु की आंतरिक स्थिति अभी भी परिवर्तनशील है।

final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;

एक संकलन त्रुटि होगी


7

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

स्रोत

यहाँ एक वस्तु को अपरिवर्तनीय बनाने पर एक मार्गदर्शिका दी गई है ।


4

अंतिम और अपरिवर्तनीय एक ही बात नहीं है। अंतिम का अर्थ है कि संदर्भ को पुन: असाइन नहीं किया जा सकता है इसलिए आप नहीं कह सकते

INSTANCE = ...

अपरिवर्तनीय का अर्थ है कि वस्तु को संशोधित नहीं किया जा सकता है। इसका एक उदाहरण java.lang.Stringवर्ग है। आप किसी स्ट्रिंग के मान को संशोधित नहीं कर सकते।


2

जावा में भाषा में निर्मित अपरिवर्तनीयता की अवधारणा नहीं है। एक उत्परिवर्ती के रूप में तरीकों को चिह्नित करने का कोई तरीका नहीं है। इसलिए भाषा में वस्तु अपरिवर्तनीयता को लागू करने का कोई तरीका नहीं है।

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