मैं सराहना करते हैं और काम Grundlefleck उसकी अस्थिरता डिटेक्टर में डाल दिया गया है की राशि प्रशंसा करता हूँ, लेकिन मुझे लगता है यह एक overkill का एक सा है।
(ध्यान दें:: यह मेरी टिप्पणी यहाँ की एक प्रति है: https://stackoverflow.com/a/28111150/773113) आप इस प्रकार एक सरल लेकिन व्यावहारिक रूप से बहुत पर्याप्त डिटेक्टर लिख सकते हैं (व्यावहारिक कि है,)
सबसे पहले, आप नहीं कर रहे हैं सिर्फ एक विधि लिखने जा रहा है जो निर्धारित करता है कि कक्षा अपरिवर्तनीय है या नहीं; इसके बजाय, आपको एक अपरिवर्तनीय डिटेक्टर कक्षा लिखनी होगी, क्योंकि इसे कुछ राज्य बनाए रखना होगा। डिटेक्टर की स्थिति अब तक की सभी कक्षाओं की खोजी अपरिवर्तनीयता होगी। यह न केवल प्रदर्शन के लिए उपयोगी है, बल्कि यह वास्तव में जरूरी है क्योंकि कक्षा में एक परिपत्र संदर्भ हो सकता है, जिससे एक सरल अपरिवर्तनीय डिटेक्टर अनंत रिकर्सन में पड़ सकता है। Unknown
, Mutable
, Immutable
, और Calculating
:
एक वर्ग की अचल चार संभावित मान हैं। आप शायद एक नक्शा बनाना चाहते हैं जो प्रत्येक कक्षा को जोड़ता है जिसे आपने अब तक अपरिवर्तनीय मूल्य के लिए सामना किया है। बेशक, Unknown
को वास्तव में लागू करने की आवश्यकता नहीं है, क्योंकि यह किसी भी वर्ग की अंतर्निहित स्थिति होगी जो अभी तक मानचित्र में नहीं है।
इसलिए, जब आप एक वर्ग की जांच शुरू करते हैं, आप इसे मानचित्र में एक Calculating
मान के साथ संबद्ध है, और जब आप समाप्त कर, आप या तो Immutable
या Mutable
साथ Calculating
बदलें।
प्रत्येक कक्षा के लिए, आपको केवल फ़ील्ड सदस्यों की जांच करने की आवश्यकता है, कोड नहीं। बाइटकोड की जांच करने का विचार गुमराह है।
सबसे पहले, आपको चाहिए नहीं जाँच है कि क्या एक वर्ग अंतिम है; कक्षा की अंतिमता इसकी अपरिवर्तनीयता को प्रभावित नहीं करती है। इसके बजाय, एक तरीका है जिसके अपरिवर्तनीय पैरामीटर उम्मीद सब से पहले अचल स्थिति डिटेक्टर आह्वान वास्तविक उद्देश्य यह है कि पारित किया गया था के वर्ग की अचल बात पर जोर देना चाहिए। यदि पैरामीटर के प्रकार के एक अंतिम वर्ग है, इसलिए अंतिम प्रदर्शन के लिए अच्छा है, लेकिन सख्ती से आवश्यक नहीं बोल इस परीक्षा छोड़ा जा सकता है। परिवर्तनशील रूप में माना जा करने के लिए इसके अलावा, के रूप में आप और नीचे देखेंगे, एक क्षेत्र है जिसका प्रकार एक गैर अंतिम वर्ग की है की घोषणा वर्ग का कारण होगा, लेकिन फिर भी हुए घोषणा की कि वर्ग की एक समस्या, गैर अंतिम की नहीं समस्या है अपरिवर्तनीय सदस्य वर्ग।अपरिवर्तनीय कक्षाओं का लंबा पदानुक्रम होना बिल्कुल ठीक है, जिसमें सभी गैर-पत्ती नोड्स निश्चित रूप से गैर-अंतिम होना चाहिए।
आपको नहीं देखना चाहिए कि कोई फ़ील्ड निजी है या नहीं; कक्षा के लिए सार्वजनिक क्षेत्र होने के लिए यह बिल्कुल ठीक है, और क्षेत्र की दृश्यता किसी भी तरह से, आकार, या रूप में घोषित कक्षा की अपरिवर्तनीयता को प्रभावित नहीं करती है। आपको केवल यह जांचने की आवश्यकता है कि फ़ील्ड अंतिम है या नहीं और इसका प्रकार अपरिवर्तनीय है।
कक्षा की जांच करते समय, आप सबसे पहले क्या करना चाहते हैं, यह super
कक्षा की अपरिवर्तनीयता निर्धारित करने के लिए है। यदि सुपर उत्परिवर्तनीय है, तो वंशज भी परिभाषा द्वारा परिवर्तनीय है।
उसके बाद, आप केवल वर्ग के घोषित क्षेत्रों, नहीं सभी क्षेत्रों की जांच करने की जरूरत है।
यदि कोई फ़ील्ड गैर-फाइनल है, तो आपकी कक्षा उत्परिवर्तनीय है।
यदि कोई फ़ील्ड अंतिम है, लेकिन फ़ील्ड का प्रकार उत्परिवर्तनीय है, तो आपकी कक्षा उत्परिवर्तनीय है। (Arrays परिभाषा mutable द्वारा हैं।)
यदि कोई फ़ील्ड अंतिम है, और फ़ील्ड का प्रकार Calculating
है, तो उसे अनदेखा करें और अगले फ़ील्ड पर जाएं। यदि सभी फ़ील्ड या तो अपरिवर्तनीय हैं या Calculating
हैं, तो आपकी कक्षा अपरिवर्तनीय है।
यदि फ़ील्ड का प्रकार एक इंटरफेस, या एक अमूर्त वर्ग, या एक गैर-अंतिम वर्ग है, तो इसे म्यूटेबल के रूप में माना जाना चाहिए, क्योंकि वास्तविक कार्यान्वयन के बारे में आपके पास बिल्कुल नियंत्रण नहीं है। यह एक दुर्बल समस्या की तरह प्रतीत हो सकता है, क्योंकि इसका मतलब है कि एक UnmodifiableCollection
के अंदर एक संशोधित संग्रह लपेटना अभी भी अपरिवर्तनीय परीक्षण में विफल रहेगा, लेकिन यह वास्तव में ठीक है, और इसे निम्नलिखित कार्यवाही के साथ संभाला जा सकता है।
कुछ कक्षाओं में गैर-अंतिम फ़ील्ड हो सकते हैं और अभी भी प्रभावी रूप से अपरिवर्तनीय हो सकते हैं। इसका एक उदाहरण String
वर्ग है। इस श्रेणी में आने वाले अन्य वर्ग वे वर्ग हैं जिनमें प्रदर्शन निगरानी उद्देश्यों (आमंत्रण काउंटर इत्यादि) के लिए पूरी तरह से गैर-अंतिम सदस्य होते हैं, जो कक्षाएं पॉपसिकल अपरिवर्तनीयता (इसे देखें) लागू करती हैं, और कक्षाएं जिनमें इंटरफेस होते हैं, किसी भी दुष्प्रभाव का कारण नहीं है। इसके अलावा, यदि किसी वर्ग में व्यापक म्यूटेबल फ़ील्ड होते हैं लेकिन वादा है कि हैशकोड() और बराबर() की गणना करते समय उन्हें ध्यान में न लेना, तो क्लास बहु-थ्रेडिंग की बात करते समय असुरक्षित है, लेकिन इसे अभी भी माना जा सकता है मानचित्र में एक कुंजी के रूप में इसका उपयोग करने के उद्देश्य से अपरिवर्तनीय।
मैन्युअल जोड़ने वर्गों (और इंटरफेस) अपने अचल स्थिति डिटेक्टर के लिए: तो, इन सभी मामलों दो तरीकों में से एक में संभाला जा सकता है। यदि आप जानते हैं कि एक निश्चित वर्ग प्रभावी रूप से अपरिवर्तनीय है, इस तथ्य के बावजूद कि इसके लिए अपरिवर्तनीय परीक्षण विफल हो जाता है, तो आप अपने डिटेक्टर में मैन्युअल रूप से एक प्रविष्टि जोड़ सकते हैं जो इसे Immutable
से संबद्ध करता है। इस तरह, डिटेक्टर कभी यह जांचने का प्रयास नहीं करेगा कि यह अपरिवर्तनीय है, यह हमेशा 'हाँ, यह है' कहेंगे।
@ImmutabilityOverride
एनोटेशन पेश करना। आपका अपरिवर्तनीय डिटेक्टर किसी क्षेत्र पर इस एनोटेशन की उपस्थिति की जांच कर सकता है, और यदि मौजूद है, तो यह क्षेत्र इस तथ्य के बावजूद अपरिवर्तनीय हो सकता है कि क्षेत्र गैर-अंतिम हो सकता है या इसका प्रकार उत्परिवर्तनीय हो सकता है। डिटेक्टर कक्षा पर इस एनोटेशन की उपस्थिति की भी जांच कर सकता है, इस प्रकार कक्षा को अपने खेतों की जांच करने के लिए भी परेशान किए बिना अपरिवर्तनीय के रूप में व्यवहार कर सकता है।
मुझे आशा है कि इससे भविष्य की पीढ़ियों में मदद मिलेगी।
शायद "isValidFieldType" अचूक करने के लिए एक पुनरावर्तन कर सकता है। :-) – marcospereira
मार्कोस्पेरिया के संशोधन के साथ, यह काफी उपयोगी हो सकता है! हम सुपरक्लस (ऑब्जेक्ट को एक विशेष मामले के रूप में अनुमति देने) पर भी भर्ती कर सकते हैं जो एक सामान्य पूर्वजों से प्राप्त करने की आवश्यकता को खत्म कर देगा। यह अच्छा है! – mcherm
ये अच्छे सुझाव हैं। मैंने सादगी और प्रदर्शन के लिए सुपरक्लास और सदस्यों पर रिकर्सिंग से बचने की कोशिश की (रिकर्सन काफी व्यापक हो सकता है)। लेकिन मैं इन सुझावों को anweser में जोड़ दूंगा। –