क्या अंतर है <? Foo> और <Foo> का विस्तार करता है


20

मुझे लगता है कि <Foo>और के बीच के अंतर के बारे में गलतफहमी है <? extends Foo>। मेरी समझ से, अगर हमारे पास था

ArrayList<Foo> foos = new ArrayList<>();

यह इंगित करता है कि प्रकार की वस्तुओं Fooको इस सरणी सूची में जोड़ा जा सकता है। चूंकि उपवर्ग Fooभी प्रकार के होते हैं Foo, इसलिए उन्हें त्रुटि के बिना भी जोड़ा जा सकता है, जैसा कि सचित्र है

ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());

जहां Bar extends Foo

अब, मान लीजिए कि मैंने परिभाषित foosकिया था

ArrayList<? extends Foo> foos = new ArrayList<>();

मेरी वर्तमान समझ यह है कि यह व्यक्त करता है some unknown type that extends Foo। मुझे इसका मतलब यह है कि कोई भी वस्तु जो उप का एक उपवर्ग है, Fooउसे इस सूची में जोड़ा जा सकता है; अर्थ है कि ArrayList<Foo>और के बीच कोई अंतर नहीं है ArrayList<? extends Foo>

इसका परीक्षण करने के लिए, मैंने निम्नलिखित कोड लिखने का प्रयास किया

ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());

लेकिन निम्नलिखित संकलन त्रुटि के साथ संकेत दिया गया था

no suitable method found for add(Foo)
method java.util.Collection.add(capture#1 of ? extends Foo) is not applicable
(argument mismatch; Foo cannot be converted to capture#1 of ? extends Foo)

no suitable method found for add(Bar)
method java.util.Collection.add(capture#2 of ? extends Bar) is not applicable
(argument mismatch; Bar cannot be converted to capture#2 of ? extends Bar)

अपनी वर्तमान समझ के आधार पर, मैं देख सकता हूं कि मैं Fooसूची में शामिल होने में सक्षम क्यों नहीं हो सकता <? extends Foo>, क्योंकि यह स्वयं का उपवर्ग नहीं है; लेकिन मैं उत्सुक हूं कि मैं Barसूची में क्यों नहीं जोड़ सकता हूं ।

मेरी समझ में छेद कहां है?



1
<? extends Foo>एक विशिष्ट और अज्ञात वर्ग है जो विस्तार करता है Foo। इस वर्ग के साथ एक ऑपरेशन केवल कानूनी है अगर यह किसी भी उपवर्ग के लिए कानूनी होगा Foo
आयुध

3
वाह। जितना अधिक आप जावा की जेनेरिक के बारे में सीखते हैं, उतने ही पेचीदा-उतावलेपन आपको मिलते हैं।
मेसन व्हीलर

जवाबों:


15

जैसा कि आपने खुद से खोजा है, एक ArrayListघोषित रूप ArrayList<? extends Foo> subFoos = new ArrayList<>();बहुत उपयोगी नहीं होगा।

<? extends T>इस पर विचार करने की उपयोगिता देखने के लिए :

List<Foo> collect( List<? extends Foo> a1, List<? extends Foo> a2 )
{
    List<Foo> collected = new ArrayList<>();
    collected.addAll( a1 );
    collected.addAll( a2 );
    return collected;
}

जिसे बाद में निम्नानुसार इस्तेमाल किया जा सकता है:

List<Foo> foos = collect( new ArrayList<Foo>(), new ArrayList<Bar>() );

या निम्नानुसार:

List<Foo> foos = collect( new ArrayList<Bar>(), new ArrayList<Foo>() );

ध्यान दें कि उपरोक्त में से कोई भी काम नहीं किया जाता यदि collectविधि निम्नानुसार घोषित की गई होती:

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