दोनों के बीच क्या अंतर है ? और जावा जेनरिक में ऑब्जेक्ट?


137

मैं जावा जेनरिक का ठीक से उपयोग करने के लिए कुछ कोड को साफ करने में मेरी मदद करने के लिए एक्लिप्स का उपयोग कर रहा हूं। अधिकांश समय यह इनफ़ॉर्मिंग प्रकारों का एक उत्कृष्ट काम कर रहा है, लेकिन कुछ मामले हैं जहां अनुमान प्रकार को यथासंभव सामान्य होना चाहिए: वस्तु। लेकिन ग्रहण मुझे एक प्रकार की वस्तु और 'एक प्रकार' के बीच चयन करने का विकल्प देता प्रतीत होता है।

तो क्या अंतर है:

HashMap<String, ?> hash1;

तथा

HashMap<String, Object> hash2;

4
Wildcards पर आधिकारिक ट्यूटोरियल देखें । यह इसे अच्छी तरह से समझाता है और उदाहरण देता है कि ऑब्जेक्ट का उपयोग करने पर यह आवश्यक क्यों है।
बेन एस

जवाबों:


148

HashMap<String, String>मैचों का एक उदाहरण Map<String, ?>लेकिन नहीं Map<String, Object>। मान लीजिए कि आप एक ऐसी विधि लिखना चाहते हैं जो Stringकिसी भी चीज़ के मानचित्र को स्वीकार करती है: यदि आप लिखेंगे

public void foobar(Map<String, Object> ms) {
    ...
}

आप आपूर्ति नहीं कर सकते HashMap<String, String>। अगर आप लिखेंगे

public void foobar(Map<String, ?> ms) {
    ...
}

यह काम करता हैं!

जावा के जेनेरिक में कभी-कभी गलतफहमी हो जाती है, जिसका List<String>कोई उप-प्रकार नहीं है List<Object>। (लेकिन String[]वास्तव में Object[], का एक उपप्रकार है , यही कारण है कि जेनरिक और सरणियाँ अच्छी तरह से मिश्रण नहीं करते हैं। (जावा में सरणियाँ सहसंयोजक हैं, जेनरिक नहीं हैं, वे अपरिवर्तनीय हैं )।

नमूना: यदि आप एक विधि है कि स्वीकार करता है लिखने के लिए चाहते हैं, तो Listकी रों InputStreamरों और के उपप्रकार InputStream, आप लिखते हैं

public void foobar(List<? extends InputStream> ms) {
    ...
}

वैसे: जोशुआ बलोच का प्रभावी जावा एक उत्कृष्ट संसाधन है जब आप जावा में इतनी सरल चीजों को नहीं समझना चाहेंगे। (आपका प्रश्न ऊपर भी पुस्तक में बहुत अच्छी तरह से कवर किया गया है।)


1
मेरे सभी नियंत्रक कार्यों के लिए नियंत्रक स्तर पर ResponseEntity <?> का उपयोग करने के लिए जाने का यह सही तरीका है?
इराकली

निर्दोष जवाब जोहान्स!
गौरव

36

इस समस्या के बारे में सोचने का एक और तरीका है

HashMap<String, ?> hash1;

के बराबर है

HashMap<String, ? extends Object> hash1;

जावा जेनरिक और कलेक्शंस के खंड (2.4) में "गेट एंड पुट प्रिंसिपल" के साथ इस ज्ञान को युगल करें :

गेट एंड पुट प्रिंसिपल: जब आप केवल किसी संरचना में मान प्राप्त करते हैं, तो सुपर वाइल्डकार्ड का उपयोग करें जब आप केवल संरचना में मान डालते हैं, और जब आप दोनों प्राप्त करते हैं तो वाइल्डकार्ड का उपयोग नहीं करते हैं।

और वाइल्ड कार्ड उम्मीद से ज्यादा काम करना शुरू कर सकता है।


1
अगर "?" आपको भ्रमित करता है, "वस्तु का विस्तार करता है" संभवतः आपको अधिक भ्रमित करेगा। शायद।
माइकल मायर्स

इस कठिन विषय के बारे में किसी एक को अनुमति देने के लिए "सोच उपकरण" प्रदान करने की कोशिश की जा रही है। वन्यजीवों के विस्तार पर अतिरिक्त जानकारी प्रदान की।
जुलिएन चास्टांग

2
अतिरिक्त सूचना के लिए धन्यवाद। मैं अभी भी इसे पचा रहा हूं। :)
स्किप्पॉपी

HashMap<String, ? extends Object> तो यह केवल nullहैशमप में जोड़े जाने से रोकता है?
मल्लाउद्दीन

12

यह समझना आसान है कि क्या आपको याद है कि Collection<Object>यह केवल एक सामान्य संग्रह है जिसमें प्रकार की वस्तुएं हैं Object, लेकिन Collection<?>सभी प्रकार के संग्रह का एक सुपर प्रकार है।


1
वहाँ एक बिंदु है कि यह बिल्कुल आसान ;-) नहीं है, लेकिन यह सही है।
सीन रेली

6

कोविर्सियस के ऊपर दिए गए उत्तर अधिकांश मामलों को कवर करते हैं लेकिन एक बात याद आती है:

"?" वर्ग पदानुक्रम में "ऑब्जेक्ट" को सम्मिलित करता है। आप कह सकते हैं कि स्ट्रिंग एक प्रकार का ऑब्जेक्ट है और ऑब्जेक्ट एक प्रकार का है? नहीं सब कुछ वस्तु से मेल खाता है, लेकिन सब कुछ मेल खाता है?

int test1(List<?> l) {
  return l.size();
}

int test2(List<Object> l) {
  return l.size();
}

List<?> l1 = Lists.newArrayList();
List<Object> l2 = Lists.newArrayList();
test1(l1);  // compiles because any list will work
test1(l2);  // compiles because any list will work
test2(l1);  // fails because a ? might not be an Object
test2(l2);  // compiled because Object matches Object

4

आप सुरक्षित रूप से कुछ भी नहीं डाल सकते हैं Map<String, ?>, क्योंकि आप नहीं जानते कि मान किस प्रकार का होना चाहिए।

आप किसी भी वस्तु को एक में डाल सकते हैं Map<String, Object>, क्योंकि मान को a Object


"आप सुरक्षित रूप से मानचित्र में कुछ भी नहीं डाल सकते हैं <स्ट्रिंग;?" गलत। यू कैन, यही इसका उद्देश्य है।
बेन एस

3
बेन गलत है, एकमात्र मूल्य जिसे आप प्रकार के संग्रह में डाल सकते हैं <?> शून्य है, जबकि आप कुछ भी टाइप <ऑब्जेक्ट> के संग्रह में डाल सकते हैं।
स्के।

2
मेरे जवाब में दिए गए लिंक से: "चूंकि हमें नहीं पता है कि सी का तत्व प्रकार किस लिए है, हम इसमें ऑब्जेक्ट नहीं जोड़ सकते हैं।" मैं गलत सूचना के लिए माफी माँगता हूँ।
बेन एस

1
सबसे बड़ी समस्या यह है कि मुझे समझ में नहीं आता कि यह कैसे संभव है कि आप कुछ भी HashMap <String;> में नहीं जोड़ सकते हैं?>, अगर हम मानते हैं कि आदिम को छोड़कर सभी वस्तुएं हैं। या यह आदिम लोगों के लिए है?
एवलॉन

1
@ अलावल अन्य जगहों पर, उस नक्शे का एक संदर्भ है जो बाध्य है। उदाहरण के लिए, यह एक हो सकता है Map<String,Integer>। केवल Integerऑब्जेक्ट को मानचित्र में मान के रूप में संग्रहीत किया जाना चाहिए। लेकिन जब से तुम मूल्य (यह के प्रकार पता नहीं है ?), तो आप अगर अगर यह सुरक्षित है कॉल करने के लिए पता नहीं है put(key, "x"), put(key, 0), या कुछ और।
इरिकसन

2

hash1एक डिक्टेट के रूप में घोषणा करते हुए HashMap<String, ?>कि वैरिएबल hash1किसी की भी HashMapकुंजी Stringऔर किसी भी प्रकार के मूल्य को पकड़ सकता है ।

HashMap<String, ?> map;
map = new HashMap<String, Integer>();
map = new HashMap<String, Object>();
map = new HashMap<String, String>();

उपरोक्त सभी मान्य है, क्योंकि चर map उन हैश मानचित्रों में से किसी को भी संग्रहीत कर सकता है। वह चर परवाह नहीं करता है कि वह किस प्रकार का हैशमैप रखता है।

एक वाइल्डकार्ड के बाद करता है नहीं , फिर भी, आप अपने नक्शे में वस्तु के किसी भी प्रकार के कर दिया करते हैं। वास्तव में, उपरोक्त हैश मैप के साथ, आप mapचर का उपयोग करके इसमें कुछ भी नहीं डाल सकते हैं :

map.put("A", new Integer(0));
map.put("B", new Object());
map.put("C", "Some String");

उपरोक्त सभी विधि कॉलों का संकलन समय-समय पर होगा, क्योंकि जावा को नहीं पता होता है कि हाशप के मूल्य प्रकार के अंदर क्या mapहै।

आप अभी भी हैश मानचित्र से एक मान प्राप्त कर सकते हैं। यद्यपि आप "मूल्य के प्रकार को नहीं जानते हैं," (क्योंकि आपको नहीं पता है कि आपके चर के अंदर किस प्रकार का हैश मैप है), आप कह सकते हैं कि सब कुछ उप-वर्ग का है Objectऔर इसलिए, जो भी आप नक्शे से बाहर निकलते हैं प्रकार की वस्तु होगी:

HashMap<String, Integer> myMap = new HashMap<>();// This variable is used to put things into the map.

myMap.put("ABC", 10);

HashMap<String, ?> map = myMap;
Object output = map.get("ABC");// Valid code; Object is the superclass of everything, (including whatever is stored our hash map).

System.out.println(output);

कोड का उपरोक्त ब्लॉक कंसोल में 10 प्रिंट करेगा।


तो, खत्म करने के लिए HashMapवाइल्डकार्ड के साथ उपयोग करें जब आपको परवाह नहीं है (यानी, इससे कोई फर्क नहीं पड़ता) HashMapउदाहरण के लिए, क्या प्रकार हैं:

public static void printHashMapSize(Map<?, ?> anyMap) {
    // This code doesn't care what type of HashMap is inside anyMap.
    System.out.println(anyMap.size());
}

अन्यथा, उन प्रकारों को निर्दिष्ट करें जिनकी आपको आवश्यकता है:

public void printAThroughZ(Map<Character, ?> anyCharacterMap) {
    for (int i = 'A'; i <= 'Z'; i++)
        System.out.println(anyCharacterMap.get((char) i));
}

उपरोक्त विधि में, हमें यह जानना होगा कि मानचित्र की कुंजी एक है Character, अन्यथा, हम यह नहीं जान पाएंगे कि इससे मान प्राप्त करने के लिए किस प्रकार का उपयोग करना है। toString()हालाँकि, सभी वस्तुओं में एक विधि होती है, इसलिए मानचित्र में इसके मूल्यों के लिए किसी भी प्रकार की वस्तु हो सकती है। हम अभी भी मूल्यों को प्रिंट कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.