178 votes

Comment puis-je ajouter à la liste <? extends Number> structures de données?

J'ai une liste qui est déclarée comme ceci:

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

J'ai essayé d'ajouter 3 à foo3. Cependant, je reçois un message d'erreur comme celui-ci:

 The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)
 

347voto

Bert F Points 27237

Désolé, mais vous ne pouvez pas.

Le générique de la déclaration d' List<? extends Number> foo3 signifie que la variable foo3 peut contenir n'importe quelle valeur à partir d'une famille de types (plutôt que d'une valeur d'un type spécifique). Cela signifie que l'un de ces cessions juridiques:

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

Donc, compte tenu de cela, quel type d'objet, pourriez-vous ajouter à l' List foo3 qui serait possible de le faire après tout ce qui précède possible ArrayList devoirs:

  • Vous ne pouvez pas ajouter un Integer car foo3 peut être interprété à une List<Double>.
  • Vous ne pouvez pas ajouter un Double car foo3 peut être interprété à une List<Integer>.
  • Vous ne pouvez pas ajouter un Number car foo3 peut être interprété à une List<Integer>.

Vous ne pouvez pas ajouter n'importe quel objet à l' List<? extends T> parce que vous ne pouvez pas garantir ce genre de List il est vraiment pointant vers, de sorte que vous ne pouvez pas garantir que l'objet est permis dans la List. La seule "garantie" est que vous ne pouvez lire et vous obtiendrez un T ou sous-classe d' T.

L'inverse de la logique s'applique à l' super, par exemple, List<? super T>. Ceux-ci sont légaux:

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

Vous ne pouvez pas lire le type spécifique T (par exemple, Number) à partir de List<? super T> parce que vous ne pouvez pas garantir ce genre de List il est vraiment à la pointe. La seule "garantie" que vous avez est que vous êtes en mesure d'ajouter une valeur de type T (ou sous-classe d' T) sans porter atteinte à l'intégrité de la liste d'être souligné.


Le parfait exemple de cela est la signature d' Collection.copy():

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

Remarquez comment l' src déclaration de la liste des utilisations extends , pour me permettre de passer une Liste à partir d'une famille de types de Liste et encore garantie il va produire des valeurs de type T ou sous-classes de T. Mais vous ne pouvez pas ajouter de l' src de la liste.

L' dest déclaration de la liste des utilisations super , pour me permettre de passer une Liste à partir d'une famille de types de Liste et encore garantie je peux écrire une valeur d'un type spécifique de T à cette liste. Mais je ne peut pas être garanti d'obtenir des valeurs de type T si j'ai lu à partir de la liste.

Alors maintenant, grâce aux génériques des caractères génériques, je peux faire l'un de ces appels de méthode unique:

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

Considérer cette confusion et très large de code pour exercer votre cerveau. Le commentaire sur des lignes qui sont illégales, et la raison en est déclaré à l'extrême droite de la ligne (besoin de faire défiler pour voir certains d'entre eux):

  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>

22voto

Carl Points 4049

Le producteur étend, Consumer Super à la rescousse!

Comprenez le mnémonique, et on répondra à votre question; voici une autre question d' actualité pour vous aider à démarrer.

19voto

sepp2k Points 157757

Vous ne pouvez pas (sans lancer dangereux). Vous pouvez seulement lire d'eux.

Le problème est que vous ne savez pas ce que la liste est exactement. Il peut s'agir d'une liste de n'importe quelle sous-classe de Number. Par conséquent, lorsque vous essayez d'y insérer un élément, vous ne savez pas si celui-ci correspond réellement à la liste.

Par exemple, la liste peut être une liste de Byte s, il serait donc erroné d'y insérer Float .

1voto

Ryan Elkins Points 2614

Vous pouvez le faire à la place:

   List<Number> foo3 = new ArrayList<Number>();      
  foo3.add(3);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X