如何添加到列表<?扩展数>数据结构? [英] How can I add to List&lt;? extends Number&gt; data structures?

查看:23
本文介绍了如何添加到列表<?扩展数>数据结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个声明如下:

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

我尝试将 3 添加到 foo3.但是我收到这样的错误消息:

I tried to add 3 to foo3. However I get an error message like this:

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

推荐答案

抱歉,您不能.

Listfoo3 意味着变量 foo3 可以保存类型族中的任何值(而不是特定类型的任何值).这意味着其中任何一个都是合法的分配:

The wildcard declaration of List<? extends Number> foo3 means that the variable foo3 can hold any value from a family of types (rather than any value of a specific type). It means that any of these are legal assignments:

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

那么,鉴于此,在上述任何可能的 ArrayList 赋值之后,您可以向 List foo3 添加什么类型的对象是合法的:

So, given this, what type of object could you add to List foo3 that would be legal after any of the above possible ArrayList assignments:

  • 您不能添加 Integer,因为 foo3 可能指向 List.
  • 您不能添加 Double,因为 foo3 可能指向 List.
  • 您不能添加Number,因为foo3 可能指向List.
  • You can't add an Integer because foo3 could be pointing at a List<Double>.
  • You can't add a Double because foo3 could be pointing at a List<Integer>.
  • You can't add a Number because foo3 could be pointing at a List<Integer>.

您不能将任何对象添加到 List 因为你不能保证它真正指向的是什么类型的 List,所以你不能保证该对象在那个 List 中是允许的>.唯一的保证"是你只能从中读取,你会得到一个 TT 的子类.

You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of T.

反向逻辑适用于super,例如<代码>列表.这些都是合法的:

The reverse logic applies to super, e.g. List<? super T>. These are legal:

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

您无法从 ListNumber)?super T> 因为你不能保证它真正指向什么样的 List .唯一的保证"您可以添加 T 类型的值(或 T 的任何子类),而不会破坏所指向列表的完整性.

You can't read the specific type T (e.g. Number) from List<? super T> because you can't guarantee what kind of List it is really pointing to. The only "guarantee" you have is you are able to add a value of type T (or any subclass of T) without violating the integrity of the list being pointed to.

最好的例子是 Collections.copy() 的签名:

The perfect example of this is the signature for Collections.copy():

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

注意 src 列表声明如何使用 extends 来允许我传递来自相关列表类型系列的任何列表,并且仍然保证它会产生类型 T 或T 的子类.但是您不能添加到 src 列表中.

Notice how the src list declaration uses extends to allow me to pass any List from a family of related List types and still guarantee it will produce values of type T or subclasses of T. But you cannot add to the src list.

dest 列表声明使用 super 允许我传递来自相关列表类型系列的任何列表,并且仍然保证我可以写入特定类型 T 的值到那个列表.但是如果我从列表中读取,则不能保证读取特定类型 T 的值.

The dest list declaration uses super to allow me to pass any List from a family of related List types and still guarantee I can write a value of a specific type T to that list. But it cannot be guaranteed to read the values of specific type T if I read from the list.

现在,多亏了泛型通配符,我可以使用单个方法执行任何这些调用:

So now, thanks to generics wildcards, I can do any of these calls with that single method:

// 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>());


考虑这个令人困惑且非常广泛的代码来锻炼你的大脑.注释掉的行是非法的,原因在行的最右边说明(需要滚动才能看到其中的一些):


Consider this confusing and very wide code to exercise your brain. The commented out lines are illegal and the reason why is stated to the extreme right of the line (need to scroll to see some of them):

  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>

这篇关于如何添加到列表<?扩展数>数据结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆