2012-12-10 19 views
7

मैं सिर्फ कुछ एक अधिक अनुभवी प्रोग्रामर द्वारा लिखे कोड को पढ़ने के लिए, और मैं निम्नलिखित भर में आया था:क्यों निजी स्थैतिक अंतिम सूची/सेट/मानचित्र अप्रचलित बनाते हैं?

public class ConsoleFormatter extends Formatter { 
    private static final Map<Level, String> PREFIXES; 

    static { 
     Map<Level, String> prefixes = new HashMap<Level, String>(); 
     prefixes.put(Level.CONFIG, "[config]"); 
     prefixes.put(Level.FINE, "[debug]"); 
     prefixes.put(Level.FINER, "[debug]"); 
     prefixes.put(Level.FINEST, "[trace]"); 
     prefixes.put(Level.INFO, "[info]"); 
     prefixes.put(Level.SEVERE, "[error]"); 
     prefixes.put(Level.WARNING, "[warning]"); 

     PREFIXES = Collections.unmodifiableMap(prefixes); 
    } 

    // ... 

} 

आप देख सकते हैं, इस स्वरूपण लॉग आउटपुट के लिए उपयोग एक वर्ग है। मेरी आंखों को पकड़ा गया, हालांकि, स्थिर प्रारंभकर्ता ब्लॉक में कोड था: PREFIXES = Collections.unmodifiableMap(prefixes);

PREFIXES क्यों एक अप्रचलित मानचित्र बनाया गया था? यह एक निजी स्थिर है, इसलिए उस वर्ग के बाहर डेटा को संशोधित करने का कोई जोखिम नहीं है। क्या निरंतर अपरिवर्तनीयता पूर्णता की भावना देने के लिए किया गया था?

व्यक्तिगत रूप से, मैं सीधे PREFIXES सीधे में एक HashMap और फिर put कुंजी-मान जोड़ों के रूप में प्रारंभ किया है होता है, एक डमी, प्लेसहोल्डर नक्शा बनाने या क्षेत्र अपरिवर्तनीय नक्शा बनाने के बिना। क्या मुझसे कोई चूक हो रही है?

+0

पूरे डेटा के PREFIXES को एकल चरण असाइनमेंट के कारण कक्षा को तुरंत चालू करते समय समवर्ती प्रारंभिक समस्याओं को रोकने के लिए _thought_ भी हो सकता है। –

उत्तर

9

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

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

+2

_ "एक दिन आप एक त्वरित फिक्स के लिए जा सकते हैं और आप मूल रूप से बनाई गई धारणा को भूल जाते हैं और शुद्धता के लिए प्रासंगिक हैं।" _ ओह लड़का, मुझे पता है कि आपका क्या मतलब है। – Konstantin

3

private मानचित्र, संग्रह या सरणी है जो कक्षा के बाहर से संशोधित है, यह आश्चर्यजनक रूप से आसान है। आप इसे final चिह्नित करेंगे, यह भी क्यों नहीं बताएगा कि यह अपरिवर्तनीय भी माना जा सकता है?

+0

मैं आपका बिंदु देखता हूं, लेकिन उल्लिखित क्षेत्र के लिए कोई गेटर्स नहीं हैं। क्या आप कह रहे हैं कि वैसे भी उन्हें अपरिवर्तनीय बनाने का अच्छा अभ्यास है, बस मामले में? – Konstantin

+1

@ KonstantinĐ। एक गेटर होने की जरूरत नहीं है। मेरा पसंदीदा उदाहरण माइकल फेदर के साथ विरासत संहिता के साथ काम कर रहा है। अध्याय 13 में वह वस्तुओं को रिसाव कैसे कर सकता है, इस बारे में सबसे अविश्वसनीय विवरण में जाता है। और अध्याय 14 में, वह एक 'निजी स्थिर' सरणी का खुलासा करता है। यदि वह ऐसा करता है, तो मैं सामान्य प्रोग्रामर को यह सही नहीं होने की उम्मीद नहीं कर रहा हूं - जब तक कि वे एक अप्रचलित रैपर के पीछे म्यूटेबल ऑब्जेक्ट को स्पष्ट रूप से छुपाएं। –

3

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

9

यदि आप गलती से return PREFIXES किसी विधि से, तो अचानक कोई अन्य कोड इसे संशोधित कर सकता है। जब आप भविष्य में उस कोड को 3AM पर संशोधित करते हैं तो स्थिरता को अपने स्वयं के मूर्खता के खिलाफ वास्तव में अपरिवर्तनीय बचाव करना।

+0

बिल्कुल ... अन्यथा 'अंतिम' 'मानचित्र <स्तर, स्ट्रिंग> PREFIXES' मानचित्र के लिए अपूर्ण होगा। – Chan

1

मानचित्र इंटरफ़ेस यह संवाद नहीं करता है कि आप कुछ अपरिवर्तनीय या अपरिवर्तनीय होना चाहते हैं।

निम्नलिखित दृष्टिकोण Eclipse Collections (पूर्व में जीएस संग्रह) में काम करेंगे।

private static final ImmutableMap<Level, String> PREFIXES = UnifiedMap.<Level, String>newMap() 
    .withKeyValue(Level.CONFIG, "[config]") 
    .withKeyValue(Level.FINE, "[debug]") 
    .withKeyValue(Level.FINER, "[debug]") 
    .withKeyValue(Level.FINEST, "[trace]") 
    .withKeyValue(Level.INFO, "[info]") 
    .withKeyValue(Level.SEVERE, "[error]") 
    .withKeyValue(Level.WARNING, "[warning]") 
    .toImmutable(); 

यह एक मानचित्र कि अनुबंध के तौर पर अपरिवर्तनीय है पैदा करेगा क्योंकि ImmutableMap अपने एपीआई में कोई परिवर्तनशील तरीकों है।

यदि आप मानचित्र इंटरफ़ेस रखना पसंद करते हैं, तो यह दृष्टिकोण भी काम करेगा।

private static final Map<Level, String> PREFIXES = UnifiedMap.<Level, String>newMap() 
    .withKeyValue(Level.CONFIG, "[config]") 
    .withKeyValue(Level.FINE, "[debug]") 
    .withKeyValue(Level.FINER, "[debug]") 
    .withKeyValue(Level.FINEST, "[trace]") 
    .withKeyValue(Level.INFO, "[info]") 
    .withKeyValue(Level.SEVERE, "[error]") 
    .withKeyValue(Level.WARNING, "[warning]") 
    .asUnmodifiable(); 

आपको नोटिस करना चाहिए कि किसी भी मामले में स्थिर ब्लॉक की आवश्यकता नहीं है।

नोट: मैं ग्रहण संग्रह के लिए एक कमिटर हूं।

0

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

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

संबंधित मुद्दे