यह एक गैर-मामूली सवाल है। असल में, आपको किसी वर्ग की किसी भी आंतरिक स्थिति के बारे में सोचना है जिसे आप किसी अन्य वर्ग को गेटटर के माध्यम से या किसी अन्य श्रेणी के सेटटर को कॉल करके देते हैं।उदाहरण के लिए, यदि आप ऐसा करते हैं: आप संभवतः दो समस्याएं हैं
Date now = new Date();
someObject.setDate(now);
// another use of "now" that expects its value to not have changed
तो:
someObject
संभवतः, "now
" का मान बदल सकता है उपरोक्त विधि अर्थ जब बाद में उपयोग करता है चर सकता है इसकी तुलना में एक अलग मूल्य है, और
- "
someObject
से गुजरने के बाद यदि आप अपना मान बदलते हैं, और someObject
ने रक्षात्मक प्रति नहीं बनाया है, तो आपनेकी आंतरिक स्थिति बदल दी है।
आपको या तो दोनों मामलों के खिलाफ संरक्षित किया जाना चाहिए, या आपको कोड के ग्राहक के आधार पर अनुमति या अस्वीकार करने की आपकी अपेक्षा को दस्तावेज करना चाहिए। एक और मामला तब होता है जब एक वर्ग में Map
होता है और आप Map
के लिए एक गेटर प्रदान करते हैं। यदि Map
ऑब्जेक्ट की आंतरिक स्थिति का हिस्सा है और ऑब्जेक्ट पूरी तरह सेMap
की सामग्री का प्रबंधन करता है, तो आपको कभीMap
बाहर जाने दें। यदि आपको मानचित्र के लिए गेटटर प्रदान करना होगा, तो myMap
के बजाय Collections.unmodifiableMap(myMap)
वापस करें। यहां आप शायद संभावित लागत के कारण क्लोन या रक्षात्मक प्रतिलिपि बनाना नहीं चाहते हैं। अपने मानचित्र को लपेटकर वापस संशोधित किया जा सकता है ताकि इसे संशोधित नहीं किया जा सके, आप अपनी आंतरिक स्थिति को किसी अन्य वर्ग द्वारा संशोधित होने से बचा रहे हैं।
कई कारणों से, clone()
अक्सर सही समाधान नहीं है। कुछ बेहतर समाधान कर रहे हैं:
- ही टिककर खेल के लिए:
- एक
Map
लौटने के बजाय, या तो keySet
करने के लिए या Map.Entry
करने के लिए या जो कुछ भी करने के लिए केवल Iterator
रों लौट यह करने की जरूरत है कि क्या करना है ग्राहक कोड की अनुमति देता है । दूसरे शब्दों में, कुछ अपने आंतरिक स्थिति का केवल-पढ़ने के लिए दृश्य है कि अनिवार्य रूप से वापस लौटने या बल्कि एक
Map
लौटने से लौटें
- अपने परिवर्तनशील राज्य वस्तु
Collections.unmodifiableMap()
- के समान अपरिवर्तनीय आवरण में लिपटे, एक
get
तरीका प्रदान कि एक कुंजी लेता है और मानचित्र से संबंधित मान देता है। यदि सभी ग्राहक Map
के साथ करेंगे, तो इससे मूल्य प्राप्त हो जाएंगे, फिर ग्राहकों को Map
स्वयं न दें; इसके बजाय, एक गेटर प्रदान करें जो Map
की get()
विधि को लपेटता है।
- कंस्ट्रक्टर्स के लिए:
- अपने वस्तु कंस्ट्रक्टर्स में उपयोग प्रतिलिपि कंस्ट्रक्टर्स कि में पारित कुछ भी की एक प्रतिलिपि बनाने के लिए परिवर्तनशील है।
- परिवर्तनीय मात्रा के बजाय, जब आप कर सकते हैं तो कन्स्ट्रक्टर तर्क के रूप में अपरिवर्तनीय मात्रा लेने के लिए डिज़ाइन करें। कभी-कभी
new Date().getTime()
द्वारा लंबे समय तक लौटने का अर्थ होता है, उदाहरण के लिए, Date
ऑब्जेक्ट के बजाए।
- जितना संभव हो उतना राज्य
final
बनाएं, लेकिन याद रखें कि final
ऑब्जेक्ट अभी भी म्यूटेबल हो सकता है और final
सरणी अभी भी संशोधित की जा सकती है।
सभी मामलों में, अगर वहाँ जो परिवर्तनशील राज्य "मालिक" के बारे में एक सवाल है, टिककर खेल या setters या कंस्ट्रक्टर्स पर यह दस्तावेज़। इसे कहीं दस्तावेज करें।
यहाँ बुरा कोड का एक तुच्छ उदाहरण है:
import java.util.Date;
public class Test {
public static void main(String[] args) {
Date now = new Date();
Thread t1 = new Thread(new MyRunnable(now, 500));
t1.start();
try { Thread.sleep(250); } catch (InterruptedException e) { }
now.setTime(new Date().getTime()); // BAD! Mutating our Date!
Thread t2 = new Thread(new MyRunnable(now, 500));
t2.start();
}
static public class MyRunnable implements Runnable {
private final Date date;
private final int count;
public MyRunnable(final Date date, final int count) {
this.date = date;
this.count = count;
}
public void run() {
try { Thread.sleep(count); } catch (InterruptedException e) { }
long time = new Date().getTime() - date.getTime();
System.out.println("Runtime = " + time);
}
}
}
आप यह देखना चाहिए कि 500 msec के लिए प्रत्येक runnable सोता है, लेकिन इसके बजाय आप गलत समय जानकारी मिलती है। यदि आप रक्षात्मक प्रतिलिपि बनाने के लिए कन्स्ट्रक्टर बदलते हैं:
public MyRunnable(final Date date, final int count) {
this.date = new Date(date.getTime());
this.count = count;
}
तो आपको सही समय की जानकारी मिलती है। यह एक मामूली उदाहरण है। आप एक जटिल उदाहरण डीबग नहीं करना चाहते हैं।
नोट: सामान्य संग्रह को व्यवस्थित करते समय ConcurrentModificationException
स्थिति को व्यवस्थित करने में विफलता का परिणाम है।
क्या आप रक्षात्मक रूप से कोड करना चाहिए? यदि आप की गारंटी दे सकते हैं कि विशेषज्ञ प्रोग्रामर की एक ही छोटी टीम हमेशा आपके प्रोजेक्ट को लिखने और बनाए रखने वाले व्यक्ति होगी, ताकि वे लगातार इस पर काम कर सकें ताकि वे परियोजना के ब्योरे की याददाश्त बनाए रख सकें, वही लोग काम करेंगे यह परियोजना के जीवनकाल के लिए, और यह परियोजना कभी "बड़ी" नहीं बन जाएगी, तो शायद आप ऐसा करने से दूर हो सकते हैं। लेकिन रक्षात्मक प्रोग्रामिंग की लागत सबसे दुर्लभ मामलों को छोड़कर बड़ी नहीं है - और लाभ बड़ा है। इसके अलावा: रक्षात्मक कोडिंग एक अच्छी आदत है। आप उन जगहों के आस-पास परिवर्तनीय डेटा को पारित करने की बुरी आदतों के विकास को प्रोत्साहित नहीं करना चाहते हैं, जिनके पास यह नहीं होना चाहिए। यह आपको कुछ दिन काट देगा। बेशक, यह सब आपके प्रोजेक्ट के आवश्यक अपटाइम पर निर्भर करता है।
आप यहां दो प्रश्न पूछ रहे हैं। आपको उन्हें विभाजित करना चाहिए। – Welbog
वे "हाथ में हाथ" के रूप में जाना था। – GreenieMeanie