जवाबों:
tl; dr: "PECS" संग्रह के दृष्टिकोण से है। यदि आप केवल सामान्य संग्रह से आइटम खींच रहे हैं , तो यह एक निर्माता है और आपको इसका उपयोग करना चाहिए extends
; यदि आप केवल सामान भर रहे हैं, तो यह एक उपभोक्ता है और आपको इसका उपयोग करना चाहिए super
। यदि आप दोनों एक ही संग्रह के साथ करते हैं, तो आपको extends
या तो उपयोग नहीं करना चाहिए या super
।
माना कि आपके पास एक ऐसा तरीका है जो इसके पैरामीटर को चीजों का एक संग्रह के रूप में लेता है, लेकिन आप इसे केवल स्वीकार करने की तुलना में अधिक लचीला होना चाहते हैं Collection<Thing>
।
केस 1: आप संग्रह के माध्यम से जाना चाहते हैं और प्रत्येक आइटम के साथ चीजें करना चाहते हैं।
फिर सूची एक निर्माता है , इसलिए आपको एक का उपयोग करना चाहिए Collection<? extends Thing>
।
तर्क यह है कि कोई Collection<? extends Thing>
भी उप-प्रकार पकड़ सकता है Thing
, और Thing
जब आप अपना ऑपरेशन करते हैं तो प्रत्येक तत्व व्यवहार करेगा । (आप वास्तव में एक के लिए कुछ भी नहीं जोड़ सकते हैं Collection<? extends Thing>
, क्योंकि आप क्रम जिस पर पता नहीं कर सकते हैं विशिष्ट की उप-प्रकार Thing
संग्रह आयोजित करता है।)
केस 2: आप चीजों को संग्रह में जोड़ना चाहते हैं।
फिर सूची एक उपभोक्ता है , इसलिए आपको एक का उपयोग करना चाहिए Collection<? super Thing>
।
यहां तर्क यह है कि इसके विपरीत Collection<? extends Thing>
, Collection<? super Thing>
हमेशा Thing
कोई फर्क नहीं पड़ता कि वास्तविक पैरामीटर प्रकार क्या है। यहाँ आप परवाह नहीं करते कि सूची में पहले से ही क्या है जब तक कि यह एक Thing
को जोड़ने की अनुमति देगा ; यह ? super Thing
गारंटी देता है।
doSomethingWithList(List list)
, तो आप सूची का उपभोग कर रहे हैं और इसलिए आपको सहसंयोजक / फैली (या एक अदृश्य सूची) की आवश्यकता होगी। दूसरी ओर यदि आपकी विधि है List doSomethingProvidingList
, तो आप सूची का निर्माण कर रहे हैं और आपको कंट्रोवर्सी / सुपर (या एक अनियंत्रित सूची) की आवश्यकता होगी।
const
C ++ में विधि मापदंडों के संदर्भ के रूप में पठनीयता में सुधार करने का एक साधन है, यह दर्शाता है कि विधि तर्कों को संशोधित नहीं करती है?
कंप्यूटर विज्ञान में इसके पीछे सिद्धांतों को कहा जाता है
? extends MyClass
,? super MyClass
औरMyClass
नीचे दी गई तस्वीर अवधारणा को समझाना चाहिए। चित्र सौजन्य: एंड्री टायरिन
PECS (निर्माता extends
और उपभोक्ता super
)
mnemonic → जाओ और रखो सिद्धांत।
यह सिद्धांत बताता है कि:
जावा में उदाहरण:
class Super {
Object testCoVariance(){ return null;} //Covariance of return types in the subtype.
void testContraVariance(Object parameter){} // Contravariance of method arguments in the subtype.
}
class Sub extends Super {
@Override
String testCoVariance(){ return null;} //compiles successfully i.e. return type is don't care(String is subtype of Object)
@Override
void testContraVariance(String parameter){} //doesn't support even though String is subtype of Object
}
Liskov प्रतिस्थापन सिद्धांत: यदि S, T का उपप्रकार है, तो T टाइप की वस्तुओं को S टाइप की वस्तुओं से बदला जा सकता है।
एक प्रोग्रामिंग भाषा के प्रकार प्रणाली के भीतर, एक टाइपिंग नियम
इस सामान्य घटना को समझने के लिए, सरणी प्रकार पर विचार करें। पशु के प्रकार के लिए हम पशु बना सकते हैं []
जावा उदाहरण:
Object name= new String("prem"); //works
List<Number> numbers = new ArrayList<Integer>();//gets compile time error
Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
myNumber[0] = 3.14; //attempt of heap pollution i.e. at runtime gets java.lang.ArrayStoreException: java.lang.Double(we can fool compiler but not run-time)
List<String> list=new ArrayList<>();
list.add("prem");
List<Object> listObject=list; //Type mismatch: cannot convert from List<String> to List<Object> at Compiletime
बाउंडेड (यानी कहीं की ओर बढ़ते हुए ) वाइल्डकार्ड : वाइल्डकार्ड के 3 अलग-अलग स्वाद हैं:
?
या ? extends Object
- अनबाउंडेड वाइल्डकार्ड। यह सभी प्रकार के परिवार के लिए खड़ा है। जब आप दोनों प्राप्त करें और उपयोग करें।? extends T
(सभी प्रकार के परिवार जो उपप्रकार हैं T
) - एक ऊपरी सीमा वाला एक वाइल्डकार्ड । T
है ऊपरी वंशानुगत पदानुक्रम में अधिकांश वर्ग। extends
जब आप केवल किसी संरचना से मान प्राप्त करते हैं तो वाइल्डकार्ड का उपयोग करें ।? super T
(सभी प्रकार के परिवार जो सुपरटेप के हैं T
) - एक वाइल्डकार्ड जिसमें कम बाउंड होता है । T
है कम वंशानुगत पदानुक्रम में अधिकांश वर्ग। एक का प्रयोग करें super
वाइल्डकार्ड जब आप केवल रखो एक संरचना में मान।नोट: वाइल्डकार्ड का ?
अर्थ है शून्य या एक बार , एक अज्ञात प्रकार का प्रतिनिधित्व करता है। वाइल्डकार्ड को एक पैरामीटर के प्रकार के रूप में इस्तेमाल किया जा सकता है, कभी भी जेनेरिक विधि इनवोकेशन के लिए एक प्रकार के तर्क के रूप में उपयोग नहीं किया जाता है, एक जेनेरिक क्लास इंस्टेंस निर्माण। (अर्थात जब वाइल्डकार्ड का उपयोग किया जाता है जो संदर्भ में उपयोग किए जाने वाले प्रोग्राम जैसे अन्य जगहों पर उपयोग नहीं किया जाता है T
)
class Shape { void draw() {}}
class Circle extends Shape {void draw() {}}
class Square extends Shape {void draw() {}}
class Rectangle extends Shape {void draw() {}}
public class Test {
/*
* Example for an upper bound wildcard (Get values i.e Producer `extends`)
*
* */
public void testCoVariance(List<? extends Shape> list) {
list.add(new Shape()); // Error: is not applicable for the arguments (Shape) i.e. inheritance is not supporting
list.add(new Circle()); // Error: is not applicable for the arguments (Circle) i.e. inheritance is not supporting
list.add(new Square()); // Error: is not applicable for the arguments (Square) i.e. inheritance is not supporting
list.add(new Rectangle()); // Error: is not applicable for the arguments (Rectangle) i.e. inheritance is not supporting
Shape shape= list.get(0);//compiles so list act as produces only
/*You can't add a Shape,Circle,Square,Rectangle to a List<? extends Shape>
* You can get an object and know that it will be an Shape
*/
}
/*
* Example for a lower bound wildcard (Put values i.e Consumer`super`)
* */
public void testContraVariance(List<? super Shape> list) {
list.add(new Shape());//compiles i.e. inheritance is supporting
list.add(new Circle());//compiles i.e. inheritance is supporting
list.add(new Square());//compiles i.e. inheritance is supporting
list.add(new Rectangle());//compiles i.e. inheritance is supporting
Shape shape= list.get(0); // Error: Type mismatch, so list acts only as consumer
Object object= list.get(0); // gets an object, but we don't know what kind of Object it is.
/*You can add a Shape,Circle,Square,Rectangle to a List<? super Shape>
* You can't get an Shape(but can get Object) and don't know what kind of Shape it is.
*/
}
}
In-variance/Non-variance: ? or ? extends Object - Unbounded Wildcard. It stands for the family of all types. Use when you both get and put.
मैं तत्व को सूची <?> या सूची <में नहीं जोड़ सकता? ऑब्जेक्ट> का विस्तार करता है, इसलिए मुझे समझ नहीं आता कि यह क्यों हो सकता है Use when you both get and put
।
?
- "अनबाउंड वाइल्डकार्ड" - आक्रमण के ठीक विपरीत के साथ मेल खाता है। कृपया निम्नलिखित दस्तावेज देखें: docs.oracle.com/javase/tutorial/java/generics/… जो बताता है: उस स्थिति में जहां कोड को चर को "इन" और "आउट" चर दोनों के रूप में एक्सेस करने की आवश्यकता होती है, वाइल्डकार्ड का उपयोग न करें। (वे "प्राप्त" और "पुट" के पर्याय के रूप में "इन" और "आउट" का उपयोग कर रहे हैं। के अपवाद के साथ null
आप एक संग्रह में जोड़ नहीं सकते हैं जिसके साथ पैरामीटर किया गया है ?
।
public class Test {
public class A {}
public class B extends A {}
public class C extends B {}
public void testCoVariance(List<? extends B> myBlist) {
B b = new B();
C c = new C();
myBlist.add(b); // does not compile
myBlist.add(c); // does not compile
A a = myBlist.get(0);
}
public void testContraVariance(List<? super B> myBlist) {
B b = new B();
C c = new C();
myBlist.add(b);
myBlist.add(c);
A a = myBlist.get(0); // does not compile
}
}
? extends B
साधन बी और कुछ भी बी का विस्तार
जैसा कि मैंने में समझाने मेरा उत्तर एक और सवाल करने के लिए, पी ई सी एस एक स्मरक मदद करने के लिए जोश बलोच द्वारा बनाई डिवाइस याद है पी roducer extends
, सी onsumer super
।
इसका मतलब यह है कि जब एक विधि के लिए पारित किया जा रहा है एक पैरामीटर प्रकार के उदाहरणों का उत्पादन होगा
T
(वे इसे किसी तरह से फिर से प्राप्त किया जाएगा) का? extends T
उपयोग किया जाना चाहिए, क्योंकि किसी उपवर्ग का कोई उदाहरणT
भी हैT
।जब एक विधि के लिए पारित किया जा रहा है एक पैरामीटर प्रकार के उदाहरणों का उपभोग करेगा
T
(वे कुछ करने के लिए इसे पारित किया जाएगा),? super T
का उपयोग किया जाना चाहिए क्योंकिT
कानूनी तौर पर किसी भी विधि को पारित किया जा सकता है जो कुछ सुपरटेप को स्वीकार करता हैT
। एकComparator<Number>
एक पर इस्तेमाल किया जा सकताCollection<Integer>
, उदाहरण के लिए।? extends T
काम नहीं करेगा, क्योंकि एकComparator<Integer>
पर काम नहीं कर सकताCollection<Number>
।
ध्यान दें कि आम तौर पर आप केवल का उपयोग कर किया जाना चाहिए ? extends T
और ? super T
कुछ विधि के मापदंडों के लिए। विधियों को केवल T
जेनेरिक रिटर्न प्रकार पर टाइप पैरामीटर के रूप में उपयोग करना चाहिए ।
संक्षेप में, पीईसीएस को याद रखने के तीन आसान नियम:
<? extends T>
यदि आपको T
किसी संग्रह से प्रकार का ऑब्जेक्ट पुनर्प्राप्त करने की आवश्यकता है, तो वाइल्डकार्ड का उपयोग करें ।<? super T>
यदि आपको T
संग्रह में प्रकार की वस्तुओं को रखने की आवश्यकता है तो वाइल्डकार्ड का उपयोग करें ।आइए मान लेते हैं यह पदानुक्रम:
class Creature{}// X
class Animal extends Creature{}// Y
class Fish extends Animal{}// Z
class Shark extends Fish{}// A
class HammerSkark extends Shark{}// B
class DeadHammerShark extends HammerSkark{}// C
आइए PE को स्पष्ट करें - निर्माता का विस्तार:
List<? extends Shark> sharks = new ArrayList<>();
आप इस सूची में "शार्क" का विस्तार करने वाली वस्तुओं को क्यों नहीं जोड़ सकते? पसंद:
sharks.add(new HammerShark());//will result in compilation error
चूँकि आपके पास एक सूची है जो रनटाइम में A, B या C प्रकार की हो सकती है , आप इसमें टाइप A, B या C की कोई भी वस्तु नहीं जोड़ सकते क्योंकि आप एक संयोजन के साथ समाप्त हो सकते हैं जो जावा में अनुमति नहीं है।
व्यवहार में, संकलक वास्तव में संकलन में देख सकता है कि आप एक बी जोड़ते हैं:
sharks.add(new HammerShark());
... लेकिन यह बताने का कोई तरीका नहीं है कि क्या रनटाइम के दौरान, आपका बी सूची प्रकार का उपप्रकार या सुपरटाइप होगा। रनटाइम के दौरान सूची प्रकार A, B, C. में से कोई भी हो सकता है। इसलिए आप उदाहरण के लिए Dead HammerShark की सूची में HammerSkark (सुपर प्रकार) को शामिल नहीं कर सकते हैं।
* आप कहेंगे: "ठीक है, लेकिन मैं इसमें HammerSkark नहीं जोड़ सकता क्योंकि यह सबसे छोटा प्रकार है।" उत्तर: यह सबसे छोटा है जिसे आप जानते हैं। लेकिन HammerSkark को किसी और के द्वारा बढ़ाया जा सकता है और आप उसी परिदृश्य में समाप्त हो सकते हैं।
आइए सीएस को स्पष्ट करें - उपभोक्ता सुपर:
उसी पदानुक्रम में हम यह कोशिश कर सकते हैं:
List<? super Shark> sharks = new ArrayList<>();
आप इस सूची में क्या और क्यों जोड़ सकते हैं?
sharks.add(new Shark());
sharks.add(new DeadHammerShark());
sharks.add(new HammerSkark());
आप उपरोक्त प्रकार की वस्तुओं को जोड़ सकते हैं क्योंकि शार्क (ए, बी, सी) के नीचे कुछ भी हमेशा शार्क (एक्स, वाई, जेड) के ऊपर किसी भी चीज का उपप्रकार होगा। समझने में आसान।
आप शार्क के ऊपर प्रकार नहीं जोड़ सकते हैं , क्योंकि रनटाइम में अतिरिक्त प्रकार की वस्तु सूची के प्रकार (एक्स, वाई, जेड) की तुलना में पदानुक्रम में अधिक हो सकती है। इसकी अनुमति नहीं है।
लेकिन आप इस सूची से क्यों नहीं पढ़ सकते हैं? (मेरा मतलब है कि आप इसमें से एक तत्व प्राप्त कर सकते हैं, लेकिन आप इसे ऑब्जेक्ट ओ के अलावा किसी भी चीज़ को नहीं दे सकते हैं):
Object o;
o = sharks.get(2);// only assignment that works
Animal s;
s = sharks.get(2);//doen't work
रनटाइम के समय, सूची का प्रकार A: X, Y, Z, ... से ऊपर का कोई भी प्रकार हो सकता है ... संकलक आपके असाइनमेंट स्टेटमेंट (जो सही लगता है) को संकलित कर सकता है, लेकिन रनटाइम के प्रकार (एनिमल) में निम्न हो सकता है सूची के घोषित प्रकार की तुलना में पदानुक्रम (जो क्रिएचर, या उच्चतर हो सकता है)। इसकी अनुमति नहीं है।
सारांश में
हम का उपयोग करें <? super T>
जोड़ने के लिए प्रकार की वस्तुओं के बराबर या इससे नीचे T
करने के लिए List
। हम इससे नहीं पढ़ सकते।
हम सूची से <? extends T>
समान या नीचे के प्रकारों की वस्तुओं को पढ़ने के लिए उपयोग करते हैं T
। हम इसमें तत्व नहीं जोड़ सकते।
(एक जवाब जोड़ना क्योंकि जेनरिक वाइल्डकार्ड के साथ कभी पर्याप्त उदाहरण नहीं)
// Source
List<Integer> intList = Arrays.asList(1,2,3);
List<Double> doubleList = Arrays.asList(2.78,3.14);
List<Number> numList = Arrays.asList(1,2,2.78,3.14,5);
// Destination
List<Integer> intList2 = new ArrayList<>();
List<Double> doublesList2 = new ArrayList<>();
List<Number> numList2 = new ArrayList<>();
// Works
copyElements1(intList,intList2); // from int to int
copyElements1(doubleList,doublesList2); // from double to double
static <T> void copyElements1(Collection<T> src, Collection<T> dest) {
for(T n : src){
dest.add(n);
}
}
// Let's try to copy intList to its supertype
copyElements1(intList,numList2); // error, method signature just says "T"
// and here the compiler is given
// two types: Integer and Number,
// so which one shall it be?
// PECS to the rescue!
copyElements2(intList,numList2); // possible
// copy Integer (? extends T) to its supertype (Number is super of Integer)
private static <T> void copyElements2(Collection<? extends T> src,
Collection<? super T> dest) {
for(T n : src){
dest.add(n);
}
}
मेरे लिए यह सबसे स्पष्ट, सरलतम तरीका है जो सुपर बनाम फैली हुई है।
extends
पढ़ने के लिए है
super
के लिए है लेखन
मुझे लगता है कि "निर्माता" कौन है और "उपभोक्ता" कौन है, इसके बारे में सोचने के लिए "पीईसीएस" एक गैर-स्पष्ट तरीका है। "पी ई सी एस" के नजरिए से परिभाषित किया गया है अपने आप डेटा संग्रह - संग्रह "खपत" यदि वस्तुओं लिखा जा रहा है करने के लिए यह (यह बुला कोड से वस्तुओं लेने वाली है), और यह "पैदा करता है" अगर वस्तुओं पढ़ा जा रहा है से (यह यह कुछ कॉलिंग कोड के लिए वस्तुओं का उत्पादन कर रहा है)। यह इस बात के लिए काउंटर है कि बाकी सब चीजों का नामकरण कैसे किया जाता है। मानक जावा एपीआई को कॉलिंग कोड के परिप्रेक्ष्य से नाम दिया गया है, न कि केवल संग्रह। उदाहरण के लिए, java.util.List के संग्रह-केंद्रित दृश्य में "ऐड ()" के बजाय "प्राप्त ()" नाम का एक तरीका होना चाहिए - आखिरतत्व, लेकिन सूची में ही तत्व प्राप्त होता है।
मुझे लगता है कि यह कोड के परिप्रेक्ष्य से चीजों के बारे में सोचने के लिए अधिक सहज, स्वाभाविक और सुसंगत है जो संग्रह के साथ बातचीत करता है - क्या कोड "से पढ़ा जाता है" या "संग्रह से लिखता है"? इसके बाद, संग्रह के लिए कोई भी कोड लिखना "निर्माता" होगा, और संग्रह से कोई भी कोड पढ़ना "उपभोक्ता" होगा।
src
और dst
। तो आप एक ही समय में कोड और कंटेनर दोनों के साथ काम कर रहे हैं और मैंने उन पंक्तियों के साथ इसके बारे में सोचना शुरू कर दिया है - "खपत कोड" एक उत्पादक कंटेनर से खपत करता है, और एक खपत कंटेनर के लिए "उत्पादन कोड" का उत्पादन होता है।
पीईसीएस "नियम" केवल यह सुनिश्चित करता है कि निम्नलिखित कानूनी है:
?
है, वह कानूनी रूप से संदर्भित कर सकता है T
?
है, इसे कानूनी रूप से संदर्भित किया जा सकता है T
की पंक्तियों के साथ विशिष्ट युग्मन List<? extends T> producer, List<? super T> consumer
केवल यह सुनिश्चित कर रहा है कि संकलक मानक "आईएस-ए" विरासत संबंध नियमों को लागू कर सकता है। यदि हम कानूनी रूप से ऐसा कर सकते हैं, तो यह कहना सरल हो सकता है <T extends ?>, <? extends T>
(या स्कैला में अभी तक बेहतर है, जैसा कि आप ऊपर देख सकते हैं [-T], [+T]
। यह दुर्भाग्य से सबसे अच्छा हम कर सकते हैं <? super T>, <? extends T>
।
जब मैंने पहली बार इसका सामना किया और इसे मेरे सिर में तोड़ दिया, तो मैकेनिक ने समझदारी दिखाई लेकिन कोड ही मुझे भ्रमित करता रहा - मैं सोचता रहा "ऐसा लगता है कि सीमा को इस तरह उलटने की जरूरत नहीं होनी चाहिए" - हालांकि मैं ऊपर स्पष्ट था - कि यह संदर्भ के मानक नियमों के अनुपालन की गारंटी देने के बारे में है।
क्या मुझे एक सादृश्य के रूप में साधारण असाइनमेंट का उपयोग करके यह देखने में मदद मिली।
निम्नलिखित पर विचार करें (उत्पादन तैयार नहीं) खिलौना कोड:
// copies the elements of 'producer' into 'consumer'
static <T> void copy(List<? extends T> producer, List<? super T> consumer) {
for(T t : producer)
consumer.add(t);
}
काम सादृश्य के संदर्भ में इस दृष्टांत, के लिए है वाइल्डकार्ड (अज्ञात प्रकार) संदर्भ - असाइनमेंट की "बाएं हाथ की ओर" - और यह सुनिश्चित करें कि जो कुछ भी है, "IS-ए ' - कि यह को सौंपा जा सकता है, क्योंकि के रूप में एक सुपर प्रकार (या अधिकांश एक ही प्रकार) है ।consumer
?
<? super T>
?
T
?
T
?
T
के लिए producer
चिंता का विषय ही यह सिर्फ उल्टे होने वाली है: producer
के ?
वाइल्डकार्ड (अज्ञात प्रकार) है दिग्दर्शन - असाइनमेंट की "दाहिने हाथ की ओर" - और <? extends T>
यह सुनिश्चित करें कि जो कुछ भी ?
है, ?
"एक है" T
- कि यह सौंपा जा सकता है एक करने के लिएT
, क्योंकि ?
एक उप प्रकार (या कम से कम एक ही प्रकार) है T
।
वास्तविक जीवन उदाहरण का उपयोग करना (कुछ सरलीकरण के साथ):
<? super FreightCarSize>
<? extends DepotSize>
सहप्रसरण : स्वीकार उपप्रकार
contravariance : supertypes स्वीकार
सहसंयोजक प्रकार केवल-पढ़ने के लिए होते हैं, जबकि contravariant प्रकार केवल-लेखन होते हैं।
उदाहरण पर एक नज़र डालते हैं
public class A { }
//B is A
public class B extends A { }
//C is A
public class C extends A { }
जेनरिक आपको सुरक्षित तरीके से गतिशील रूप से प्रकारों के साथ काम करने की अनुमति देता है
//ListA
List<A> listA = new ArrayList<A>();
//add
listA.add(new A());
listA.add(new B());
listA.add(new C());
//get
A a0 = listA.get(0);
A a1 = listA.get(1);
A a2 = listA.get(2);
//ListB
List<B> listB = new ArrayList<B>();
//add
listB.add(new B());
//get
B b0 = listB.get(0);
चूंकि जावा का संग्रह एक संदर्भ प्रकार है जिसके परिणामस्वरूप हमारे पास अगले मुद्दे हैं:
समस्या # 1
//not compiled
//danger of **adding** non-B objects using listA reference
listA = listB;
* स्विफ्ट की जेनेरिक में ऐसी समस्या नहीं है क्योंकि कलेक्शन Value type
[अबाउट] इसलिए एक नया कलेक्शन बनाया गया है
समस्या # 2
//not compiled
//danger of **getting** non-B objects using listB reference
listB = listA;
वाइल्डकार्ड एक संदर्भ प्रकार की विशेषता है और इसे सीधे इंस्टेंट नहीं किया जा सकता है
समाधान # 1
<? super A>
उर्फ कम बाउंड उर्फ कंट्रोवर्सी उर्फ उपभोक्ता गारंटी देता है कि यह ए और सभी सुपरक्लेसेस द्वारा संचालित है, इसीलिए इसे जोड़ना सुरक्षित है
List<? super A> listSuperA;
listSuperA = listA;
listSuperA = new ArrayList<Object>();
//add
listSuperA.add(new A());
listSuperA.add(new B());
//get
Object o0 = listSuperA.get(0);
समाधान # 2
<? extends A>
उर्फ अपर बाउंड उर्फ कोवरियनस उर्फ निर्माता गारंटी देता है कि यह ए और सभी उपवर्गों द्वारा संचालित होता है, यही कारण है कि इसे प्राप्त करना और डालना सुरक्षित है
List<? extends A> listExtendsA;
listExtendsA = listA;
listExtendsA = listB;
//get
A a0 = listExtendsA.get(0);
super
हिस्सा बताती है , लेकिन दूसरे का एक विचार देती है।