2008-10-30 10 views
7

मैंने संग्रह के लिए विशिष्टता देखी है।कुछ सामान्य क्लास <? super T> जावा जेनेरिक प्रकारों में SomeClass <T> के बराबर क्यों नहीं है?

public static <T> void sort(List<T> list, Comparator<? super T> c) 

"? super" क्यों आवश्यक है? यदि ClassBClassA को बढ़ाता है, तो क्या हमारे पास गारंटी नहीं होगी कि Comparator<ClassA> "? super" भाग के बिना, दो ClassB ऑब्जेक्ट्स की तुलना करने में सक्षम होगा?

दूसरे शब्दों में, यह कोड दिया गया है:

List<ClassB> list = . . . ; 
Comparator<ClassA> comp = . . . ; 
Collections.sort(list, comp); 

संकलक इतने स्मार्ट क्यों नहीं जानते हैं कि यह संग्रह .sort() की घोषणा के लिए "? super" निर्दिष्ट किए बिना भी ठीक है?

उत्तर

7

जोश ब्लोच ने इस वर्ष Google I/O पर एक बात की थी, जिसे Effective Java Reloaded कहा जाता है, जिसे आप दिलचस्प पाते हैं। यह "पेक्स" नामक एक नींबू के बारे में बात करता है (निर्माता extends, उपभोक्ता super), जो बताता है कि आप अपने इनपुट पैरामीटर में केवल ? extends T और ? super T का उपयोग क्यों करते हैं (केवल; कभी भी वापसी प्रकारों के लिए नहीं), और जब इसका उपयोग करना है।

+0

धन्यवाद, यह एक उपयोगी प्रस्तुति है। मुझे लगता है कि मेरी समस्या की जड़ पहली असली स्लाइड है: सूची सूची की उप-वर्ग नहीं है, जिस तरह से स्ट्रिंग [] ऑब्जेक्ट का उप-वर्ग है []। – Kip

0

यह आपके लिए स्पष्ट है कि, Comparator के मामले में, T के किसी भी पूर्वजों का काम होगा। लेकिन संकलक यह नहीं जानता कि कक्षा Comparator इस तरह के कार्यों - इसे सिर्फ यह बताया जाना चाहिए कि इसे <T> या <? super T> की अनुमति देनी चाहिए या नहीं।

एक और तरीका देखा गया, हाँ यह सच है कि किसी पूर्वजों के Comparator इस मामले में काम करेंगे - और लाइब्रेरी डेवलपर का तरीका यह है कि <? super T> का उपयोग करना है।

+0

लेकिन यह मेरे लिए बिल्कुल स्पष्ट नहीं है - तुलनात्मक का अर्थ है कि इसमें कुछ फ़ंक्शन हैं जो केवल प्रकार के ऑब्जेक्ट्स पर काम करते हैं। चूंकि कक्षा बी की सभी वस्तुएं क्लासए की ऑब्जेक्ट्स हैं, तुलनात्मक के सभी फ़ंक्शन जो केवल क्लासए पर काम करेंगे कक्षाबी पर भी काम करते हैं। कोई मानव ज्ञान आवश्यक नहीं है AFAIK – Kip

+0

@ किप: फिर, देखें कि जोश ब्लोच यह देखने के लिए बात करते हैं कि जेनेरिक को डिज़ाइन किया गया था ताकि फू _ooot_ को Foo से बढ़ाया गया हो, भले ही व्युत्पन्न स्वयं बेस से विस्तारित हो। :-) –

1

यह सी # के समान है, मैंने अभी कुछ दिनों पहले इसके बारे में सीखा था कि क्यों (कठिन तरीका, और फिर पीडीसी सूचनात्मक तरीका)।

मान लें Dog extends Animal

Blah<Dog>नहीं वे पूरी तरह से अलग प्रकार हस्ताक्षर भले ही Dog फैली Animal है Blah<Animal> के समान है।

उदाहरण के लिए Blah<T> पर एक विधि मान:

T Clone(); 

Blah<Dog> इस में Dog Clone(); है, जबकि Blah<Animal> में इस Animal Clone(); है।

आप भेद करने के लिए संकलक कह सकते हैं कि Blah<Dog>Blah<Animal> का एक ही सार्वजनिक इंटरफ़ेस है कि एक तरह से की जरूरत है और वह है क्या <? super T> इंगित करता है - टी के रूप में इस्तेमाल किसी भी वर्ग Blah<? super T> के संदर्भ में अपने सुपर वर्ग को कम किया जा सकता है।

(सी # 4.0 में इस Blah<out T> मेरा मानना ​​है कि हो सकता है।)

6

वहाँ More Fun with Wildcards में इस का एक वास्तव में अच्छा है (लेकिन twisty) व्याख्या दी गई है।

0

आपके प्रश्न का सरल जवाब यह है कि पुस्तकालय डिजाइनर लाइब्रेरी के उपयोगकर्ता को अधिकतम लचीलापन देना चाहता था; उदाहरण के लिए इस विधि हस्ताक्षर आप इस तरह कुछ करने के लिए अनुमति देता है:

List<Integer> ints = Arrays.asList(1,2,3); 
Comparator<Number> numberComparator = ...; 

Collections.sort(ints, numberComparator); 

का उपयोग वाइल्डकार्ड आप एक Comparator<Integer> उपयोग करने के लिए मजबूर किया जा रहा से रोकता है; तथ्य यह है कि भाषा को पुस्तकालय डिजाइनर द्वारा निर्दिष्ट वाइल्डकार्ड की आवश्यकता होती है, जिससे वह या तो इस तरह के उपयोग को अनुमति या प्रतिबंधित कर सकता है।

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