2016-08-18 8 views
17

के साथ अनियमितताओं का मानना ​​है कि जेनिक्स में ? टाइप विशिष्ट अज्ञात प्रकार है। जिसका अर्थ है, बताएं कि उस प्रकार की एक सूची हमें किसी भी प्रकार की वस्तु को जोड़ने से रोकती है।(?) वाइल्डकार्ड जेनेरिक प्रकार

List<?> unknownList; 
unknownList.add(new Object()); // This is an error. 

कंपाइलर अपेक्षित त्रुटि देता है।

लेकिन जब अज्ञात प्रकार दूसरा स्तर जेनरिक है, तो कंपाइलर परवाह नहीं लगती है।

class First<T> {} 

List<First<?>> firstUnknownList; 

// All these three work fine for some reason. 
firstUnknownList.add(new First<>()); 
firstUnknownList.add(new First<Integer>()); 
firstUnknownList.add(new First<String>()); 

मैंने सोचा था कि शायद संकलक बिल्कुल दूसरे स्तर में सामान्य पैरामीटर के बारे में परवाह नहीं करता है, लेकिन यह मामला नहीं है,

List<First<Integer>> firstIntegerList; 
firstIntegerList.add(new First<String>()); // This gives a compiler error as expected. 

तो, क्यों संकलक हमें किसी भी तरह जोड़ने की अनुमति देता तत्व के जब केवल एक अज्ञात तत्व (और इसलिए कुछ भी नहीं) दूसरे उदाहरण में स्वीकार्य है?

नोट: संकलक जावा 1.8

+0

'नया () '' सूची ' में जोड़ने के बाद, 'आप फिर से क्या कर सकते हैं असुरक्षित है? कल्पना करें कि आपके पास निर्माता 0''और उपभोक्ता' 'विधि' पहले 'पर विधि है: आप उपभोक्ता को नहीं बुला सकते हैं; और आप निर्माता से 'ऑब्जेक्ट' प्राप्त कर सकते हैं। इस प्रकार, इसके बारे में कुछ भी असुरक्षित नहीं है - जब तक कि मुझे एक स्पष्ट मामला याद नहीं आ रहा है। –

+3

"और इसलिए कुछ नहीं" 'शून्य 'को छोड़कर। –

+0

ए 'सूची ' को 'सूची ' निर्दिष्ट किया जा सकता था और फिर ऑब्जेक्ट * जोड़ना गलत है। 'सूची 'करेंगे। –

उत्तर

13

आप एक List<T> के लिए कुछ भी है कि आप प्रकार T के संदर्भ में स्टोर कर सकते हैं जोड़ सकते हैं:

T item = ... 
List<T> list = new ArrayList<>(); 
list.add(item); 

First<?>First<T> के महाप्रकार है;

First<?> first = new First<String>(); 

तो, T प्रतिस्थापन ऊपर First<?> के लिए: ताकि आप एक First<T> के लिए एक संदर्भ प्रकार First<?> के एक चर में स्टोर कर सकते हैं

First<?> item = new First<String>(); 
List<First<?>> list = new ArrayList<>(); 
list.add(item); 

सभी कि ओपी के उदाहरण में हो रहा है यह है कि अस्थायी चर item छोड़ दिया जाता है:

firstUnknownList.add(new First<String>()); 

हालांकि, अगर आपके साथ ऐसा करउदाहरण:

First<Integer> item = new First<String>(); // Compiler error. 
List<First<Integer>> list = new ArrayList<>(); 
list.add(item); 

यह स्पष्ट है क्यों जिसकी अनुमति नहीं है: आप item का काम नहीं कर सकता।


यह भी देखना होगा कि आप उस सूची की सामग्री के साथ कुछ भी असुरक्षित ऐसा नहीं कर सकते संभव है।

आप इंटरफ़ेस करने के तरीकों की एक जोड़ी जोड़ते हैं:

interface First<T> { 
    T producer(); 
    void consumer(T in); 
} 

अब, पर विचार क्या आप तत्वों है कि आप सूची में जोड़ा के साथ क्या कर सकते हैं:

for (First<?> first : firstUnknownList) { 
    // OK at compile time; OK at runtime unless the method throws an exception. 
    Object obj = first.producer(); 

    // OK at compile time; may fail at runtime if null is not an acceptable parameter. 
    first.consumer(null); 

    // Compiler error - you can't have a reference to a ?. 
    first.consumer(/* some maybe non-null value */); 
} 

तो वहाँ isn ' वास्तव में कुछ भी नहीं है जो आप वास्तव में उस सूची के तत्वों के साथ कर सकते हैं जो प्रकार की सुरक्षा का उल्लंघन करेंगे (बशर्ते आप कच्चे प्रकारों का उपयोग करने के लिए इसका उल्लंघन करने के लिए कुछ भी नहीं करेंगे)। आप यह दिखा सकते हैं कि जेनेरिक निर्माता/उपभोक्ता विधियां संकलक द्वारा समान रूप से सुरक्षित या प्रतिबंधित हैं।

तो ऐसा करने के लिए आपको कोई कारण नहीं है।

+0

समझ गया ... 'कुछ ' विशिष्ट जेनेरिक प्रकारों का एक सुपरटेप नहीं है। धन्यवाद... – Codebender

4

मैं First इंटरफ़ेस Box इंटरफ़ेस के लिए

Box<?> uknownBox ग्रे बॉक्स कुछ के साथ में यह

Box<Apple> appleBox बॉक्स सेब के साथ

List<Box<Apple>> appleBoxList कई बक्से सेब

List<Box<?>> uknownBoxList कई अज्ञात धूसर रंग के बॉक्स के साथ बदल देंगे

,210

appleBoxList.add(new Box<Orange>()) - सेब बक्से की सूची में संतरे के साथ बॉक्स नहीं जोड़ सकते हैं

unknownBoxList.add(new Box<?>()) - हम क्या है कि धूसर रंग के बॉक्स में है पता नहीं है, एक और अज्ञात ग्रे बॉक्स जोड़ने कुछ भी नहीं

unknownBoxList.add(new Box<Orange>()) - same for concrete boxes 

unknownBoxList.add(new Box<Apple>()) - since you are not allowed to 'open' them 

unknownBoxList = appleBoxList इस बदलता है सेब बॉक्स सूची में ग्रे (संभवतः सेब नहीं) बक्से जोड़ने से रोकने के लिए संकलित नहीं करता है। पिछले ऑपरेशन की वजह से कानूनी है।

4

यह सबटाइप/सुपरटेप-रिश्तों के बारे में है।

List<?> एक सूची है जिसमें अज्ञात (लेकिन विशिष्ट) प्रकार के तत्व होते हैं। आप इस सूची में कभी भी नहीं जानते कि किस प्रकार बिल्कुल निहित है। तो अगर आप इसे करने के लिए वस्तुओं नहीं जोड़ सकते हैं, क्योंकि वे गलत प्रकार का हो सकता है:

List<Integer> ints = new ArrayList<Integer>(); 
List<?> unknowns = ints; 

// It this worked, the list would contain a String.... 
unknowns.add("String"); 

// ... and this would crash with some ClassCastException 
Integer i = ints.get(0); 

यह भी स्पष्ट हो सकता है कि आप

List<Number> numbers = null; 
Integer integer = null; 
numbers.add(integer); 

क्या कर सकते हैं यह काम करता है क्योंकि Number एक है Integer का सच्चा सुपरटेप। यह एक सूची में एक और विशिष्ट प्रकार की वस्तु जोड़ने के लिए प्रकार की सुरक्षा का उल्लंघन नहीं करता है।


दूसरे उदाहरण के बारे में प्रमुख मुद्दा है:

First<?> हर First<T>

के महाप्रकार है आप कर सकते हैं हमेशा की तरह

First<Integer> fInt = null; 
First<Integer> fString = null; 

First<?> f = null; 
f = fInt; // works 
f = fString; // works 

तो के कारण कुछ करने के लिए आप First<String> को List<First<?>> में क्यों जोड़ सकते हैं w हाय आप Integer को List<Number> पर जोड़ सकते हैं: जिस तत्व को आप जोड़ना चाहते हैं वह एक वास्तविक उप प्रकार सूची में अपेक्षित तत्वों का है।

0

मुझे विश्वास है कि इस प्रकार का? जेनेरिक में एक विशिष्ट अज्ञात प्रकार है।

यह थोड़ा गलत है।हाँ, एक वाइल्डकार्ड प्रकार एक अज्ञात प्रकार के लिए खड़ा है, लेकिन अलग अलग समय पर अलग-अलग प्रकार के लिए खड़े हो सकते हैं:

List<?> list = new ArrayList<String>(); 
list = new ArrayList<Integer>(); 

केवल अपरिवर्तनीय एक अभिव्यक्ति है जिसका प्रकार एक वाइल्डकार्ड हमेशा जिसका प्रकार है कि के अनुरूप एक मूल्य निकलेगा जिसमें है वाइल्डकार्ड। चूंकि प्रत्येक मान में एक प्रकार का वाइल्डकार्ड नहीं होता है, इसलिए कोई भी कह सकता है कि वाइल्डकार्ड किसी भी समय (अधिक) "विशिष्ट" प्रकार के लिए खड़ा है।

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