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

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

问题描述

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

我试着给foo3加3。然而,我收到了这样的错误消息:

 方法add(capture#1 of?extends Number)类型为List< ;捕获#1的? 
扩展数字>不适用于参数(ExtendsNumber)


解决方案

对不起,但你不能。



List的通配符声明<?扩展Number> foo3 表示变量 foo3 可以保存来自一系列类型的任何值(而不是特定类型的任何值)。这意味着任何这些都是合法的任务:

 列表< ;?扩展Number> foo3 = new ArrayList< Number>; // NumberextendsNumber 
List< ;?扩展Number> foo3 = new ArrayList< Integer>; // Integer extends Number
List< ;?扩展Number> foo3 = new ArrayList< Double>; // Double extends Number

所以,给定这个类型的对象可以添加到 List foo3 在上述任何可能的 ArrayList 赋值之后都是合法的:




  • 您无法添加整数,因为 foo3 可能指向一个列表< Double>

  • 因为您不能添加 Double foo3 可能指向列表<整数>

  • 您可以因为 foo3 可能指向一个列表<整数> code>。



您无法将任何对象添加到 List< ;?因为你不能保证它真的指向什么样的 List ,所以你不能保证该对象是允许的在 List 中。唯一的保证是你只能从中读取,你会得到 T 或者是 T 的子类。 。

反向逻辑适用于 super ,例如列表与LT ;? super T> 。这些是合法的:

 列表< ;?超级号码> foo3 = new ArrayList< Number>; // Number是Number 
的超级列表< ;?超级号码> foo3 = new ArrayList< Object>; // Object是Number的一个超级b $ b

您无法读取特定类型T(例如 Number )from List <? super T> ,因为你不能保证它真的指向什么样的 List 。您唯一的保证是您可以添加 T 类型的值(或 T ),而不违反所指向的列表的完整性。




完美的例子是签名对于 Collections.copy()

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

注意 src 列表声明使用 extends 来允许我从一系列相关列表类型中传递任何列表,并仍然保证它将生成T类型或T的子类型的值。但是不能添加到 src 列表中。



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

所以,现在,由于泛型通配符,我可以用这种方法完成这些调用:

  //复制(dest,src)
集合。 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());






考虑一下这个令人困惑和非常宽泛的代码,脑。注释掉的行是非法的,为什么要在行的最右边说明原因(需要滚动查看其中的一些):

  List< Number> listNumber_ListNumber = new ArrayList< Number>(); 
//列表<号码> listNumber_ListInteger = new ArrayList< Integer>(); //错误 - 只能正确分配< Number>
//列表<号码> listNumber_ListDouble = new ArrayList< Double>(); //错误 - 只能正确分配< Number>

列表< ;?扩展Number> listExtendsNumber_ListNumber = new ArrayList< Number>();
列表< ;?扩展Number> listExtendsNumber_ListInteger = new ArrayList< Integer>();
列表< ;?扩展Number> listExtendsNumber_ListDouble = new ArrayList< Double>();

列表< ;?超级号码> listSuperNumber_ListNumber = new ArrayList< Number>();
//列表< ;?超级号码> listSuperNumber_ListInteger = new ArrayList< Integer>(); //错误 - 整数不是Number
的超类// List <?超级号码> listSuperNumber_ListDouble = new ArrayList< Double>(); //错误 - Double不是Number的超类


// List< Integer> listInteger_ListNumber = new ArrayList< Number>(); //错误 - 只能正确指定<整数>
列表<整数> listInteger_ListInteger = new ArrayList< Integer>();
//列表< Integer> listInteger_ListDouble = new ArrayList< Double>(); //错误 - 只能正确指定<整数>

//列表< ;?扩展Integer> listExtendsInteger_ListNumber = new ArrayList< Number>(); //错误 - 数字不是整数
的子类List <?扩展Integer> listExtendsInteger_ListInteger = new ArrayList< Integer>();
//列表< ;?扩展Integer> listExtendsInteger_ListDouble = new ArrayList< Double>(); //错误 - Double不是Integer的子类

List< ;?超整型> listSuperInteger_ListNumber = new ArrayList< Number>();
列表< ;?超整型> listSuperInteger_ListInteger = new ArrayList< Integer>();
//列表< ;?超整型> listSuperInteger_ListDouble = new ArrayList< Double>(); //错误 - Double不是Integer的超类


listNumber_ListNumber.add(3); // ok - 允许将整数加到List< Number>

//接下来的3个编译错误是出于同样的原因:
//你不知道什么样的List< T>实际上是
//被引用 - 它可能无法保存整数。
//你不能添加任何东西(不是Object,Number,Integer,
//也不是Double)到List <?扩展Number>
//listExtendsNumber_ListNumber.add(3); //错误 - 无法将整数添加到* possible * List< Double>,尽管它实际上是List< Number>
//listExtendsNumber_ListInteger.add(3); //错误 - 无法将Integer添加到* possible * List< Double>,尽管它实际上是List< Integer>
//listExtendsNumber_ListDouble.add(3); //错误 - 无法将Integer添加到* possible * List< Double>,尤其是因为它实际上是List< Double>

listSuperNumber_ListNumber.add(3); // ok - 允许将Integer添加到List< Number>或列表<对象>

listInteger_ListInteger.add(3); // ok - 允许将整数加到列表< Integer> (duh)

//由于上述相同的原因,失败 - 你不能
//保证什么样的List var真的是
//指向
//listExtendsInteger_ListInteger.add(3); //错误 - 无法将Integer添加到* possible * List< X>只允许持有X的

listSuperInteger_ListNumber.add(3); // ok - 允许将整数添加到List< Integer> ;, List< Number>或List< Object>
listSuperInteger_ListInteger.add(3); // ok - 允许将整数添加到List< Integer> ;, List< Number>或List< Object>


I have a List which is declared like this :

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

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)

解决方案

Sorry, but you can't.

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

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:

  • 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>.

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.

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

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.


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

public static <T> void copy(List<? super T> dest,List<? extends 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.

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>

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

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