Kaip pridėti prie sąrašo <? plečia skaičių> duomenų struktūras?

Turiu sąrašą, kuris skelbiamas taip:

  List<? extends Number> foo3 = new ArrayList<Integer>(); 

Bandžiau pridėti 3 prie foo3. Tačiau gaunu tokį klaidos pranešimą:

 The method add(capture#1-of ? extends Number) in the type List<capture#1-of ? extends Number> is not applicable for the arguments (ExtendsNumber) 
101
06 мая '10 в 0:38 2010-05-06 00:38 nustatė unj2 gegužės 06 d. 10 val. 0:38 2010-05-06 00:38
@ 3 atsakymai

Atsiprašome, bet jūs negalite.

Laukinių ženklų deklaracijos List<? extends Number> foo3 List<? extends Number> foo3 reiškia, kad kintamasis foo3 gali turėti bet kokios rūšies šeimos vertę (o ne bet kurios rūšies vertę). Tai reiškia, kad bet kuris iš jų yra teisinis priskyrimas:

 List<? extends Number> foo3 = new ArrayList<Number>; // Number "extends" Number List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number List<? extends Number> foo3 = new ArrayList<Double>; // Double extends Number 

Turint tai omenyje, kokio tipo objektą pridėtumėte prie List foo3 , kuris būtų teisėtas po bet kurio iš anksčiau nurodytų „ ArrayList užduočių:

  • Jūs negalite pridėti Integer , nes foo3 gali nukreipti į List<Double> .
  • Negalite pridėti Double , nes foo3 gali nukreipti į List<Integer> .
  • Negalite pridėti Number , nes foo3 gali nukreipti į List<Integer> .

Jūs negalite pridėti jokių objektų į List<? extends T> List<? extends T> , nes negalite garantuoti, kokio tipo List jis faktiškai rodo, todėl negalite garantuoti, kad objektas yra leidžiamas šiame List . Vienintelė „garantija“ yra ta, kad jūs galite ją perskaityti tik T ir T arba subklasę T

Pavyzdžiui, atvirkštinė logika taikoma super . List<? super T> List<? super T> . Tai teisėta:

 List<? super Number> foo3 = new ArrayList<Number>; // Number is a "super" of Number List<? super Number> foo3 = new ArrayList<Object>; // Object is a "super" of Number 

Jūs negalite skaityti konkretaus tipo T (pvz., Number ) iš List<? super T> List<? super T> , nes negalite garantuoti, kokio tipo List jis tikrai rodo. Vienintelė „garantija“ yra ta, kad galite pridėti T tipo (arba bet kurio T poklasio) vertę nepažeidžiant sąrašo, kurį jis nurodo, vientisumą.


Puikus pavyzdys yra parašų Collections.copy() :

 public static <T> void copy(List<? super T> dest,List<? extends T> src) 

Atkreipkite dėmesį, kad src sąrašo deklaracijoje extends , kad galėčiau perduoti bet kurio sąrašo tipą iš susijusių sąrašų tipų ir vis tiek įsitikinti, kad jis sukuria T tipo arba T poklasių vertes.

super deklaraciją naudoja super , kad galėčiau perduoti bet kurio sąrašo sąrašą iš susijusių sąrašų tipų ir vis dėlto užtikrinti, kad į šį sąrašą galėčiau įrašyti tam tikro tipo T vertę. Tačiau negali būti garantuota, kad perskaitysiu tam tikro tipo T vertes, jei perskaičiau iš sąrašo.

Taigi, generinių vaistų generinių vaistų dėka, galiu atlikti bet kurį iš šių skambučių naudojant šį vieną būdą:

 // copy(dest, src) Collections.copy(new ArrayList<Number>(), new ArrayList<Number()); Collections.copy(new ArrayList<Number>(), new ArrayList<Integer()); Collections.copy(new ArrayList<Object>(), new ArrayList<Number>()); Collections.copy(new ArrayList<Object>(), new ArrayList<Double()); 

Apsvarstykite šį sudėtingą ir labai platų kodą, kad galėtumėte naudoti savo smegenis. Komentuotos eilutės yra neteisėtos ir priežastis pateikta dešinėje linijos pusėje (turi būti slenkama, kad pamatytumėte kai kuriuos iš jų):

  List<Number> listNumber_ListNumber = new ArrayList<Number>(); //List<Number> listNumber_ListInteger = new ArrayList<Integer>(); // error - can assign only exactly <Number> //List<Number> listNumber_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Number> List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>(); List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>(); List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>(); List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>(); //List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>(); // error - Integer is not superclass of Number //List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>(); // error - Double is not superclass of Number //List<Integer> listInteger_ListNumber = new ArrayList<Number>(); // error - can assign only exactly <Integer> List<Integer> listInteger_ListInteger = new ArrayList<Integer>(); //List<Integer> listInteger_ListDouble = new ArrayList<Double>(); // error - can assign only exactly <Integer> //List<? extends Integer> listExtendsInteger_ListNumber = new ArrayList<Number>(); // error - Number is not a subclass of Integer List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>(); //List<? extends Integer> listExtendsInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a subclass of Integer List<? super Integer> listSuperInteger_ListNumber = new ArrayList<Number>(); List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>(); //List<? super Integer> listSuperInteger_ListDouble = new ArrayList<Double>(); // error - Double is not a superclass of Integer listNumber_ListNumber.add(3); // ok - allowed to add Integer to exactly List<Number> // These next 3 are compile errors for the same reason: // You don't know what kind of List<T> is really // being referenced - it may not be able to hold an Integer. // You can't add anything (not Object, Number, Integer, // nor Double) to List<? extends Number> //listExtendsNumber_ListNumber.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Number> //listExtendsNumber_ListInteger.add(3); // error - can't add Integer to *possible* List<Double>, even though it is really List<Integer> //listExtendsNumber_ListDouble.add(3); // error - can't add Integer to *possible* List<Double>, especially since it is really List<Double> listSuperNumber_ListNumber.add(3); // ok - allowed to add Integer to List<Number> or List<Object> listInteger_ListInteger.add(3); // ok - allowed to add Integer to exactly List<Integer> (duh) // This fails for same reason above - you can't // guarantee what kind of List the var is really // pointing to //listExtendsInteger_ListInteger.add(3); // error - can't add Integer to *possible* List<X> that is only allowed to hold X's listSuperInteger_ListNumber.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object> listSuperInteger_ListInteger.add(3); // ok - allowed to add Integer to List<Integer>, List<Number>, or List<Object> 
215
06 мая '10 в 1:48 2010-05-06 01:48 atsakė Bertui F gegužės 06 d. 10 d. 1:48 2010-05-06 01:48

Jūs negalite (be pavojaus). Galite juos perskaityti tik.

Problema ta, kad jūs nežinote, kuris sąrašas yra sąrašas. Tai gali būti bet kurio skaičiaus poklasio sąrašas, todėl, kai bandote įdėti elementą į jį, jūs nežinote, kad elementas tikrai atitinka sąrašą.

Pavyzdžiui, „List“ gali būti „ Byte sąrašas, todėl būtų klaida, jei „ Float į jį būtų įtrauktas.

13
06 мая '10 в 0:39 2010-05-06 00:39 atsakymas pateikiamas sepp2k 06 gegužės 10 d. 0:39 2010-05-06 00:39

Vietoj to galite tai padaryti:

  List<Number> foo3 = new ArrayList<Number>(); foo3.add(3); 
2
06 мая '10 в 0:48 2010-05-06 00:48 atsakymą pateikė „ Ryan Elkins“ gegužės 10 d. 10 val. 0:48 2010-05-06 00:48

Kiti klausimai apie „ žymų arba „ Klauskite“