2009-05-16 15 views
49

java.util.Properties क्लास एक मानचित्र का प्रतिनिधित्व करने के लिए है जहां कुंजी और मान दोनों स्ट्रिंग हैं। ऐसा इसलिए है क्योंकि Properties ऑब्जेक्ट्स .properties फ़ाइलों को पढ़ने के लिए उपयोग किए जाते हैं, जो टेक्स्ट फ़ाइलें हैं।java.util.Properties मानचित्र <ऑब्जेक्ट, ऑब्जेक्ट> और मानचित्र क्यों नहीं लागू करता है <स्ट्रिंग, स्ट्रिंग>

तो, जावा 5 में क्यों वे इस वर्ग Map<Object,Object> और नहीं Map<String,String> लागू करने के लिए पुनः स्थापित किया था?

javadoc कहता है:

क्योंकि गुण Hashtable से विरासत, पुट और putAll तरीकों एक गुण वस्तु के लिए लागू किया जा सकता है। उनका उपयोग दृढ़ता से निराश होता है क्योंकि वे कॉलर को उन प्रविष्टियों को सम्मिलित करने की अनुमति देते हैं जिनकी चाबियाँ या मान स्ट्रिंग नहीं हैं। इसके बजाय सेटप्रोपर्टी विधि का उपयोग किया जाना चाहिए। यदि स्टोर या सेव विधि को "समझौता" गुण ऑब्जेक्ट पर कॉल किया जाता है जिसमें गैर-स्ट्रिंग कुंजी या मान होता है, तो कॉल विफल हो जाएगी।

चूंकि कुंजी और मान दोनों स्ट्रिंग होने के लिए हैं, तो उचित सामान्य प्रकार का उपयोग करके स्थिर रूप से लागू क्यों न करें?

मैं Properties लागू Map<String,String> पूरी तरह से पिछड़े पूर्व जावा 5. के लिए लिखा आप पुराने कोड है कि चिपक गैर तार है, तो कोड के साथ संगत में एक गुण वस्तु तो है कि कोड अब जावा 5 के साथ संकलन होगा नहीं होगा बनाने लगता है। लेकिन ... क्या यह अच्छी बात नहीं है? संकलन समय पर ऐसी प्रकार की त्रुटियों को पकड़ने के लिए जेनेरिकों का पूरा बिंदु नहीं है?

उत्तर

50

क्योंकि उन्होंने जावा के शुरुआती दिनों में जल्दी में ऐसा किया था, और यह नहीं पता था कि प्रभाव चार संस्करण बाद में क्या होगा।

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

दुर्भाग्य से, अगर वे पूर्वव्यापी प्रभाव से Map<String, String> से Properties इनहेरिट बनाने के लिए थे, उसके बाद निम्न पहले से मान्य कोड काम करना बंद होगा:

Map<Object, Object> x = new Properties() 
x.put("flag", true) 

क्यों किसी को भी है कि क्या करना होगा मुझे परे है, लेकिन में पश्च संगतता के लिए सूर्य की प्रतिबद्धता जावा व्यर्थ से परे वीरता से परे चला गया है।

अब सबसे शिक्षित पर्यवेक्षकों द्वारा सराहना की जाती है कि Properties को कभी भी Map से विरासत में नहीं मिला होना चाहिए। इसके बजाय इसे Map के चारों ओर लपेटना चाहिए, जो केवल उन मानचित्रों को उजागर करता है जो समझ में आते हैं।

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

+1

असल में मानचित्र x = new Properties() किसी भी तरह से काम करते हैं। इसके लोग गुणों जैसे बटन डालते हैं। ("ध्वज", बूलियन। टीआरयूई); मैंने लोगों को सभी प्रकार के डेटा को गुण वस्तु में रखा है, लेकिन कभी भी गैर-स्ट्रिंग कुंजी नहीं है। ;) –

+0

मैंने स्पष्ट करने के लिए अपना उत्तर अपडेट कर दिया है, धन्यवाद। –

+5

एक मिनट रुको! मानचित्र <ऑब्जेक्ट, ऑब्जेक्ट> एक्स = नई प्रॉपर्टीज() कानूनी प्री-जावा 5 नहीं है, <ऑब्जेक्ट, ऑब्जेक्ट> सिंटैक्स जावा 5 में पेश किया गया था। इसलिए कथन "पहले वैध कोड" गलत है। –

2

कारण: Liskov substitution principle और पीछे की संगतता। PropertiesHashtable बढ़ाता है और इस प्रकार Hashtable स्वीकार करने वाले सभी संदेशों को स्वीकार करना होगा - और इसका मतलब है put(Object, Object) स्वीकार करना। और इसे Hashtable<String, String> के बजाय सादा Hashtable का विस्तार करना है क्योंकि जेनिक्स को type erasure के माध्यम से नीचे-compatibe तरीके से कार्यान्वित किया गया था, इसलिए संकलक ने अपनी बात पूरी करने के बाद, कोई जेनरिक नहीं है।

+3

मुझे नहीं लगता कि Liskov प्रतिस्थापन सिद्धांत यह से कोई लेना देना नहीं है है। जब आप कक्षा प्राप्त करते हैं तो जावा खुशी से आपको जेनेरिक प्रकारों को परिष्कृत करने देता है। यही कारण है कि <टी Sometype> और <टी सुपर Sometype> वाक्यविन्यास मौजूद है। –

27

यह मूल रूप से इरादा था कि Properties वास्तव में Hashtable<String,String> फैलाएगा। दुर्भाग्यवश पुल विधियों के कार्यान्वयन में समस्या आई। Properties इस तरह से परिभाषित किया गया है कि जावैक सिंथेटिक तरीकों को उत्पन्न करता है। Properties को परिभाषित करना चाहिए, get विधि जो String लौटाती है लेकिन Object लौटने वाली विधि को ओवरराइड करने की आवश्यकता है। तो एक सिंथेटिक पुल विधि जोड़ा जाता है।

मान लीजिए कि आपके पास पुराने पुराने 1.4 दिनों में एक कक्षा लिखी गई थी। आपने Properties में कुछ विधियों को ओवरराइड कर दिया है। लेकिन आपने जो नहीं किया है वह नई विधियों को ओवरराइड कर दिया गया है। यह अनपेक्षित व्यवहार की ओर जाता है। इन पुल विधियों से बचने के लिए, PropertiesHashtable<Object,Object> बढ़ाता है। इसी तरह Iterable एक (केवल पढ़ने के लिए) SimpleIterable वापस नहीं करता है, क्योंकि इससे Collection कार्यान्वयन के तरीकों को जोड़ा गया होगा।

+2

अच्छी व्याख्या। मैंने इसके बारे में भी सोचा है। –

13

वन-लाइनर (कोई चेतावनी के लिए दो-लाइनर) गुण से मानचित्र बनाने के लिए:

@SuppressWarnings({ "unchecked", "rawtypes" }) 
Map<String, String> sysProps = new HashMap(System.getProperties()); 
+0

प्रश्न का उत्तर नहीं देता है। लेकिन जवाब देता है कि सवाल पहली जगह क्यों हुआ। सीधा मुद्दे पर। –

+1

क्या "कच्ची प्रकार" जरूरी है? (कम से कम मेरे इंटेलिजे आईडीईए में, "अनचेक" किसी भी चेतावनी को दबाने के लिए पर्याप्त है।) – Jonik

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