2009-03-24 20 views
102

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

HashMap<String, ?> hash1; 

और

HashMap<String, Object> hash2; 
+1

[वाइल्डकार्ड्स] (http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html) पर आधिकारिक ट्यूटोरियल देखें। यह अच्छी तरह से बताता है और ऑब्जेक्ट का उपयोग करने के लिए यह आवश्यक क्यों है इसका एक उदाहरण देता है। –

उत्तर

103

HashMap<String, String> मैचों Map<String, ?> का एक उदाहरण नहीं बल्कि Map<String, Object>:

तो बीच क्या फर्क है। आप

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

आप एक HashMap<String, String> की आपूर्ति नहीं कर सकते हैं बारे में चाहते हैं: आप एक विधि है कि कुछ भी करने के लिए String रों से नक्शे को स्वीकार करता है लिखने के लिए चाहते हैं। यदि आप

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

लिखते हैं तो यह काम करता है!

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

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

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

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

+1

मेरे सभी नियंत्रक कार्यों के लिए नियंत्रक स्तर पर ResponseEntity का उपयोग करने का यह सही तरीका है? – Purmarili

3

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

आप किसी ऑब्जेक्ट को Map<String, Object> में डाल सकते हैं, क्योंकि मान को Object माना जाता है।

+0

"आप सुरक्षित रूप से मानचित्र में कुछ भी नहीं डाल सकते हैं" झूठी। आप कर सकते हैं, यह उसका उद्देश्य है। –

+0

गलत, बेन। ऐसा करने से "अनचेक" चेतावनियां उत्पन्न होंगी। वाइल्डकार्ड का उद्देश्य कोड लिखना है जो किसी भी सामान्य प्रकार पर काम कर सकता है। – erickson

+1

बेन गलत है, एकमात्र मूल्य जिसे आप के संग्रह में डाल सकते हैं, शून्य है, जबकि आप प्रकार के संग्रह में कुछ भी डाल सकते हैं। –

7

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

+1

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

23

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

HashMap<String, ?> hash1; 

को

HashMap<String, ? extends Object> hash1; 

युगल "जाओ और सिद्धांत रखो" खंड में (2 के साथ इस ज्ञान बराबर है।4) Java Generics and Collections से:

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

और वाइल्ड कार्ड अधिक समझदारी से शुरू कर सकता है।

+0

अगर "?" आपको भ्रमित करता है, "ऑब्जेक्ट बढ़ाता है" आपको अधिक भ्रमित कर देगा। शायद। –

+0

किसी को इस कठिन विषय के बारे में तर्क देने के लिए "सोच उपकरण" प्रदान करने का प्रयास करना। वाइल्डकार्ड को विस्तारित करने के लिए अतिरिक्त जानकारी प्रदान की गई। –

+1

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

1

सहप्रसरण कवर ज्यादातर मामलों ऊपर जवाब लेकिन एक बात याद आती है: "?"

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

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 
संबंधित मुद्दे