क्या इसमें कोई अंतर है
List<Map<String, String>>
तथा
List<? extends Map<String, String>>
?
यदि कोई अंतर नहीं है, तो उपयोग करने का क्या लाभ है ? extends
?
क्या इसमें कोई अंतर है
List<Map<String, String>>
तथा
List<? extends Map<String, String>>
?
यदि कोई अंतर नहीं है, तो उपयोग करने का क्या लाभ है ? extends
?
जवाबों:
अंतर यह है कि, उदाहरण के लिए, ए
List<HashMap<String,String>>
एक है
List<? extends Map<String,String>>
लेकिन नहीं
List<Map<String,String>>
इसलिए:
void withWilds( List<? extends Map<String,String>> foo ){}
void noWilds( List<Map<String,String>> foo ){}
void main( String[] args ){
List<HashMap<String,String>> myMap;
withWilds( myMap ); // Works
noWilds( myMap ); // Compiler error
}
आप एक लगता होगा List
की HashMap
एक होना चाहिए List
की Map
है, लेकिन इसका कोई खास कारण है क्यों यह नहीं है:
मान लीजिए आप कर सकते हैं:
List<HashMap<String,String>> hashMaps = new ArrayList<HashMap<String,String>>();
List<Map<String,String>> maps = hashMaps; // Won't compile,
// but imagine that it could
Map<String,String> aMap = Collections.singletonMap("foo","bar"); // Not a HashMap
maps.add( aMap ); // Perfectly legal (adding a Map to a List of Maps)
// But maps and hashMaps are the same object, so this should be the same as
hashMaps.add( aMap ); // Should be illegal (aMap is not a HashMap)
तो यही कारण है कि एक List
के HashMap
एक नहीं होना चाहिए List
की Map
है।
HashMap
एक है Map
बहुरूपता की वजह से।
List
के HashMap
एक नहीं है List
की Map
रों।
List<Map<String,String>> maps = hashMaps;
और HashMap<String,String> aMap = new HashMap<String, String>();
, तब भी आप पाएंगे कि maps.add(aMap);
अवैध है जबकि hashMaps.add(aMap);
कानूनी है। इसका उद्देश्य गलत प्रकारों को जोड़ना रोकना है, लेकिन यह सही प्रकारों को जोड़ने की अनुमति नहीं देगा (संकलनकर्ता संकलन समय के दौरान "सही" प्रकार का निर्धारण नहीं कर सकता है)
HashMap
Map
आप List<NavigableMap<String,String>>
पहले जैसे प्रकारों के साथ अभिव्यक्ति प्रदान नहीं कर सकते ।
(आप को पता है तुम क्यों नहीं सौंप सकते चाहते हैं List<String>
के लिए List<Object>
एक को देखने के असंख्य इतने पर अन्य प्रश्न।)
List<String>
का उपप्रकार नहीं है List<Object>
? - देखें, उदाहरण के लिए, stackoverflow.com/questions/3246137/…
? extends
। न ही यह सुपर / उपप्रकारों या सह / विरोधाभासी (यदि कोई है) के साथ सहसंबंध की व्याख्या करता है।
अन्य उत्तरों में मुझे जो याद आ रहा है, वह इस संदर्भ में है कि यह सामान्य और विशेष रूप से सह-और विपरीत और उप- और सुपरटिप्स (यानी, बहुरूपता) से कैसे संबंधित है। यह अच्छी तरह से ओपी द्वारा समझा जा सकता है, लेकिन सिर्फ मामले में, यहाँ यह जाता है:
आप एक वर्ग है, तो Automobile
, तो Car
और Truck
उनके उपप्रकार हैं। किसी भी कार को प्रकार ऑटोमोबाइल के एक चर को सौंपा जा सकता है, यह OO में अच्छी तरह से जाना जाता है और इसे बहुरूपता कहा जाता है। Covariance इसी सिद्धांत का उपयोग जेनेरिक या डेलिगेट्स के साथ परिदृश्यों में करता है। जावा में प्रतिनिधि (अभी तक) नहीं हैं, इसलिए यह शब्द केवल जेनरिक पर लागू होता है।
मैं मानक पॉलीमॉर्फिज़्म के रूप में सहसंयोजक के बारे में सोचता हूं कि आप बिना सोचे-समझे काम करने की क्या उम्मीद करेंगे, क्योंकि:
List<Car> cars;
List<Automobile> automobiles = cars;
// You'd expect this to work because Car is-a Automobile, but
// throws inconvertible types compile error.
हालाँकि, त्रुटि का कारण सही है: List<Car>
से विरासत में नहीं मिलता है List<Automobile>
और इस प्रकार एक दूसरे को नहीं सौंपा जा सकता है। केवल सामान्य प्रकार के मापदंडों का एक अंतर्निहित संबंध है। कोई यह सोच सकता है कि जावा कंपाइलर बस इतना स्मार्ट नहीं है कि वह आपके परिदृश्य को ठीक से समझ सके। हालाँकि, आप उसे संकेत देकर कंपाइलर की मदद कर सकते हैं:
List<Car> cars;
List<? extends Automobile> automobiles = cars; // no error
सह-विचरण का उल्टा विपरीत है। जहां सहसंयोजक में पैरामीटर प्रकार का एक उप-प्रकार संबंध होना चाहिए, वहीं प्रतिवाद में उनके पास एक सुपर-टाइप संबंध होना चाहिए। इसे एक ऊपरी विरासत के रूप में माना जा सकता है: किसी भी सुपरपाइप को अनुमति दी जाती है और निर्दिष्ट प्रकार सहित:
class AutoColorComparer implements Comparator<Automobile>
public int compare(Automobile a, Automobile b) {
// Return comparison of colors
}
इसका उपयोग कलेक्शन.सोर्ट के साथ किया जा सकता है :
public static <T> void sort(List<T> list, Comparator<? super T> c)
// Which you can call like this, without errors:
List<Car> cars = getListFromSomewhere();
Collections.sort(cars, new AutoColorComparer());
आप इसे एक तुलनित्र के साथ भी कह सकते हैं जो वस्तुओं की तुलना करता है और किसी भी प्रकार के साथ इसका उपयोग करता है।
थोड़ा सा OT शायद, आपने नहीं पूछा, लेकिन यह आपके प्रश्न का उत्तर देने में मदद करता है। सामान्य तौर पर, जब आप कुछ प्राप्त करते हैं, तो सहसंयोजक का उपयोग करें और जब आप कुछ डालते हैं, तो विरोधाभासी का उपयोग करें। स्टैक ओवरफ्लो प्रश्न के उत्तर में यह सबसे अच्छी तरह से समझाया गया है कि जावा जेनरिक में कंट्रोवर्सी का उपयोग कैसे किया जाएगा?।
List<? extends Map<String, String>>
आप उपयोग करते हैं extends
, इसलिए सहसंयोजक के लिए नियम लागू होते हैं। यहां आपके पास मानचित्रों की एक सूची है और सूची में आपके द्वारा संग्रहीत प्रत्येक आइटम एक Map<string, string>
या उससे प्राप्त होना चाहिए । बयान List<Map<String, String>>
से प्राप्त नहीं सकता Map
है, लेकिन होना चाहिए एक Map
।
इसलिए, निम्नलिखित काम करेगा, क्योंकि TreeMap
इनसे विरासत में मिली Map
:
List<Map<String, String>> mapList = new ArrayList<Map<String, String>>();
mapList.add(new TreeMap<String, String>());
लेकिन यह नहीं होगा:
List<? extends Map<String, String>> mapList = new ArrayList<? extends Map<String, String>>();
mapList.add(new TreeMap<String, String>());
और यह या तो काम नहीं करेगा, क्योंकि यह सहसंयोजक बाधा को संतुष्ट नहीं करता है:
List<? extends Map<String, String>> mapList = new ArrayList<? extends Map<String, String>>();
mapList.add(new ArrayList<String>()); // This is NOT allowed, List does not implement Map
यह शायद स्पष्ट है, लेकिन आपने पहले ही नोट किया होगा कि extends
कीवर्ड का उपयोग केवल उस पैरामीटर पर लागू होता है, बाकी पर नहीं। यानी, निम्नलिखित संकलन नहीं करेगा:
List<? extends Map<String, String>> mapList = new List<? extends Map<String, String>>();
mapList.add(new TreeMap<String, Element>()) // This is NOT allowed
मान लीजिए आप स्ट्रिंग के रूप में एक कुंजी के साथ नक्शे में किसी भी प्रकार की अनुमति देना चाहते हैं, तो आप extend
प्रत्येक प्रकार के पैरामीटर पर उपयोग कर सकते हैं । यानी, मान लीजिए कि आप XML प्रोसेस करते हैं और आप AttrNode, Element आदि को मैप में स्टोर करना चाहते हैं, तो आप कुछ ऐसा कर सकते हैं:
List<? extends Map<String, ? extends Node>> listOfMapsOfNodes = new...;
// Now you can do:
listOfMapsOfNodes.add(new TreeMap<Sting, Element>());
listOfMapsOfNodes.add(new TreeMap<Sting, CDATASection>());
List<? extends Map<String, String>> mapList = new ArrayList<? extends Map<String, String>>(); mapList.add(new TreeMap<String, String>());
में परिणाम found: ? extends java.util.Map<java.lang.String,java.lang.String> required: class or interface without bounds
। List<Map<String, String>> mapList = new ArrayList<Map<String, String>>(); mapList.add(new TreeMap<String, String>());
अच्छी तरह से काम। अंतिम उदाहरण स्पष्ट रूप से सही है।
आज, मैंने इस सुविधा का उपयोग किया है, इसलिए यहां मेरा बहुत ताजा वास्तविक जीवन उदाहरण है। (मैंने सामान्य लोगों के वर्ग और विधि के नाम बदल दिए हैं ताकि वे वास्तविक बिंदु से विचलित न हों।)
मेरे पास एक ऐसा तरीका है जो Set
उन A
वस्तुओं को स्वीकार करने के लिए है जिन्हें मैंने मूल रूप से इस हस्ताक्षर के साथ लिखा था:
void myMethod(Set<A> set)
लेकिन यह वास्तव में इसे Set
उपवर्गों के साथ कॉल करना चाहता है A
। लेकिन इसकी अनुमति नहीं है! (इसका कारण यह है कि myMethod
वस्तुओं को set
उस प्रकार से जोड़ सकते हैं A
, लेकिन उप-प्रकार के नहींset
ऑब्जेक्ट को कॉलर की साइट पर घोषित किया जाता है। इसलिए यह टाइप सिस्टम को तोड़ सकता है यदि यह संभव था।)
अब यहां बचाव के लिए जेनरिक आते हैं, क्योंकि यह इस तरीके से काम करता है जैसे कि मैं इस पद्धति के हस्ताक्षर का उपयोग करता हूं:
<T extends A> void myMethod(Set<T> set)
या कम, यदि आपको विधि बॉडी में वास्तविक प्रकार का उपयोग करने की आवश्यकता नहीं है:
void myMethod(Set<? extends A> set)
इस प्रकार, set
प्रकार वास्तविक उपप्रकार की वस्तुओं का एक संग्रह बन जाता है A
, इसलिए प्रकार प्रणाली को खतरे में डाले बिना उपवर्गों के साथ इसका उपयोग करना संभव हो जाता है।
जैसा कि आपने उल्लेख किया है, सूची को परिभाषित करने के दो निम्न संस्करण हो सकते हैं:
List<? extends Map<String, String>>
List<?>
2 बहुत खुला है। यह किसी भी वस्तु प्रकार को पकड़ सकता है। यह उस मामले में उपयोगी नहीं हो सकता है जब आप किसी दिए गए प्रकार का नक्शा चाहते हैं। यदि कोई व्यक्ति गलती से एक अलग प्रकार का मानचित्र बनाता है, उदाहरण के लिए,Map<String, int>
,। आपकी उपभोक्ता पद्धति टूट सकती है।
यह सुनिश्चित करने के लिए कि List
किसी दिए गए प्रकार की वस्तुओं को धारण किया जा सकता है, जावा जेनरिक ने पेश किया ? extends
। तो # 1 में, List
किसी भी वस्तु को पकड़ सकता है जो कि Map<String, String>
प्रकार से ली गई है । किसी अन्य प्रकार के डेटा को जोड़ने से एक अपवाद होगा।