2012-03-19 22 views
7

में अपरिवर्तनीय एक वर्ग अपरिवर्तनीय मैं क्या कर सकता बनाने के लिए कर रही है:एक वर्ग जावा

1) बनाओ वर्ग अंतिम
2) setters
3 प्रदान नहीं करते हैं) के रूप में अंतिम

सभी चर को चिह्नित लेकिन अगर मेरी कक्षा तो कुछ अन्य वर्ग के किसी अन्य वस्तु है, somone उस वस्तु

class MyClass{ 
final int a; 
final OtherClass other 

MyClass(int a ,OtherClass other){ 
    this.a = a; 
    this.other = other; 
} 

int getA(){ 
    return a; 
} 

OtherClass getOther(){ 
    return other; 
} 

public static void main(String ags[]){ 
    MyClass m = new Myclass(1,new OtherClass); 
    Other o = m.getOther(); 
    o.setSomething(xyz) ; //This is the problem ,How to prevent this? 

} 
} 
+4

सेट विधि –

+0

@LuiggiMendoza नहीं लिखते हैं, मुझे लगता है कि अन्य/अन्य क्लास एक वर्ग होने का मतलब है जिसे वह नियंत्रित नहीं करता है। –

+3

अन्य कक्षा के लिए एक रैपर लिखें, और केवल गेटर्स बनाएं। – Nican

उत्तर

3

ए) OtherClass अपरिवर्तनीय रूप में अच्छी तरह

या

बी बनाओ) OtherClass वस्तु के लिए सीधी पहुँच की अनुमति न दें, बजाय केवल टिककर खेल प्रॉक्सी की तरह कार्य करने के लिए प्रदान करते हैं। जोड़ने

संपादित करने के लिए: आप OtherClass की गहरी प्रतिलिपि बना सकता है और मूल के बजाय एक प्रति लौटने के लिए, लेकिन यह है कि आम तौर पर व्यवहार के प्रकार आप जावा में उम्मीद करेंगे नहीं है।

1

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

यदि आप getOther को हटा नहीं सकते हैं, तो इसे getOtherView पर बदलें और other के केवल-पढ़ने के दृश्य को वापस करें। सभी विधियों के लिए रैपर होंगे, लेकिन कोई सेट नहीं है।

1

अपने गेटर्स से गहरे क्लोन लौटें। आपको यह आसान काम नहीं मिल सकता है।

1

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

public class MyImmutable { 
    private MutableClass mutableObject; 
} 

... आप getMutableObject() विधि, क्योंकि ऐसा करने से बाहर संशोधन के लिए द्वार खोल देगा प्रदान नहीं कर सकते, इस तरह:

myImmutable.getMutableObject().setSomeAttribute(newValue); 

एक के रूप में उपर्युक्त का विशेष मामला, Collections कक्षा में ummodifiableXXX() विधियों के साथ, सभी संग्रह और/या मानचित्रों को अपरिवर्तनीय बनाया जाना चाहिए।

1

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

1

लेकिन मेरी कक्षा तो कुछ अन्य वर्ग के किसी अन्य वस्तु है, तो somone उस वस्तु का मूल्य बदल सकते ...

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

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

2

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

  1. एक बाहरी उपयोगकर्ता के लिए कोई रास्ता नहीं वस्तु
  2. एक गारंटी नहीं है कि किसी भी समय उपयोगकर्ता पढ़ता है या में वस्तु के मूल्य का उपयोग करता है के मूल्य को बदलने के लिए भविष्य में, यह एक ही परिणाम मिल जाएगा

महत्वपूर्ण नोट: यह वास्तव में जब तक एक अपरिवर्तनीय वस्तु अंदर परिवर्तनशील डेटा के लिए ठीक है के रूप में यह एपीआई उपयोगकर्ता के नजरिए से एक अपरिवर्तनीय वस्तु के रूप में व्यवहार। उदाहरण के लिए java.lang.String पर विचार करें: हालांकि इसे आम तौर पर निश्चित अपरिवर्तनीय वर्ग के रूप में माना जाता है, लेकिन वास्तव में हैशकोड को कैश करने के लिए यह एक परिवर्तनीय आंतरिक क्षेत्र है (बहुत से लोग इसे नहीं जानते हैं!)।

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

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

ये सभी समाधान थोड़ा हैकी हैं - कुल मिलाकर एक बेहतर समाधान अपरिवर्तनीय वस्तुओं के भीतर उत्परिवर्तनीय वस्तुओं के उपयोग से बचने के लिए है। लंबे समय तक यह परेशानी के लिए पूछ रहा है क्योंकि जल्दी या बाद में एक परिवर्तनीय संदर्भ रिसाव हो जाएगा और आपको बग खोजने में बहुत मुश्किल होगी। बेहतर होगा कि तुम अपरिवर्तनीय वस्तुओं की एक पूरी पदानुक्रम (दृष्टिकोण स्काला और Clojure जैसी भाषाओं से लिये गये) की ओर बढ़ रहे

+0

लगभग किसी ऑब्जेक्ट जिसमें एक परिवर्तनीय आकार के संग्रह होते हैं, एक बैकिंग स्टोर के रूप में एक सरणी होने जा रहा है, इसलिए नेस्टेड म्यूटेबल ऑब्जेक्ट्स से पूरी तरह से परहेज करना आम तौर पर व्यावहारिक नहीं है (केवल किसी भी सरणी के साथ किया जा सकता है जो अपरिवर्तनीय पेड़ों का उपयोग करके किया जा सकता है, लेकिन कई मामलों में सरणी तीव्रता के क्रम से अधिक होगी)। – supercat

1

यह तरीके निम्नलिखित

'1.Don टी सेटर प्रदान करें द्वारा जावा में अपरिवर्तनीय वर्ग बनाने के लिए संभव है तरीकों।

2. सभी फ़ील्ड को अंतिम और निजी बनाएं।

3. कक्षा को अंतिम रूप में बनाएं।

+0

केवल तभी मान्य होते हैं जब फ़ील्ड अपरिवर्तनीय हों। – KillBill