我如何添加到列表 < ? 扩展数字 > 数据结构?

我尝试将3添加到 foo3,但是我得到了如下错误消息:

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

你不能(没有不安全的石膏)。你只能从他们读取。

> Float into it
86734 次浏览

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

  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>

你可以这样做:

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

抱歉,但你不能。

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

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中添加什么类型的对象是合法的:

    “ List’<’? extNumber > 实际上是一个 上界通配符!

  • 不能添加 Integer,因为 foo3可能指向 List<Double>
  • 不能添加 Double,因为 foo3可能指向 List<Integer>
  • 上限通配符表示,任何扩展 Number 或 Number 本身的类都可以用作形式参数类型:

  • 不能添加 Number,因为 foo3可能指向 List<Integer>

您不能向 List<? extends T>添加任何对象,因为您不能保证它实际指向的是哪种类型的 List,所以您不能保证该对象在该 List中是允许的。唯一的“保证”是您只能从中读取,并且您将得到 TT的子类。

反向逻辑适用于 super,例如 List<? super T>。这些是合法的:

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

你不能从 List<? super T>中读取特定类型的 T (例如 Number) ,因为你不能保证它真正指向的是哪种类型的 List。唯一的“保证”是您能够添加 T类型的值(或者 T的任何子类) ,而不会破坏所指向列表的完整性。


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

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

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

问题的根源在于 Java 不知道 List 的类型确实如此。

dest列表声明使用 super允许我传递相关 List 类型家族中的任何 List,并且仍然保证我可以向该列表写入特定类型 T 的值。但是不能保证从列表中读取 具体点类型 T 的值。

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

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

它必须是一个精确的和独特的类型。我希望它有所帮助:)

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

  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>

那么,给定这个,在上述任何可能的 ArrayList赋值之后,你可以在 List foo3中添加什么类型的对象是合法的:

  • 不能添加 Integer,因为 foo3可能指向 List<Double>
  • 不能添加 Double,因为 foo3可能指向 List<Integer>
  • 尽管我在这里读到了答案,但它还是让我感到困惑,直到我发现了帕维尔•米纳耶夫(Pavel Minaev)的评论:

  • 不能添加 Number,因为 foo3可能指向 List<Integer>

注意,List < ? extNumber > 并不意味着“ List of object of

您不能向 List<? extends T>添加任何对象,因为您不能保证它实际指向的是哪种类型的 List,所以您不能保证该对象在该 List中是允许的。唯一的“保证”是您只能从中读取,并且您将得到 TT的子类。

反向逻辑适用于 super,例如 List<? super T>。这些是合法的:

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

你不能从 List<? super T>中读取特定类型的 T (例如 Number) ,因为你不能保证它真正指向的是哪种类型的 List。唯一的“保证”是您能够添加 T类型的值(或者 T的任何子类) ,而不会破坏所指向列表的完整性。


不同的类型,所有这些类型都扩展了 Number”。它的意思是“列表的

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

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

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

dest列表声明使用 super允许我传递相关 List 类型家族中的任何 List,并且仍然保证我可以向该列表写入特定类型 T 的值。但是不能保证从列表中读取 具体点类型 T 的值。

扩展了 Number 的单个类型的对象”

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

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

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

  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>

在上面的示例中,您实际上不需要使用 (List<?>),但是您可能需要在代码中使用它,这取决于给定的 list类型。

请注意,使用 ?将会给出编译器警告,直到您将其置于函数之上:

@SuppressWarnings("unchecked")

因为 untypedListsuperclassedListtrulyclassedList只是对 list的引用,所以仍然需要向原始 ArrayList 添加元素。

可能的复制品:

在上面的示例中,您实际上不需要使用 (List<?>),但是您可能需要在代码中使用它,这取决于给定的 list类型。

请注意,使用 ?将会给出编译器警告,直到您将其置于函数之上:

@SuppressWarnings("unchecked")
使用 CSS 内容 添加 HTML 实体

#sitenavmenu-content-menu li:before
{
content:"|&nbsp;&nbsp;";
}

因为3是 primitive (int),它不扩展 Number,所以可以添加它的盒装类型 (Integer.valueOf(3))。虽然它在 IDEA中显示为错误,但它仍然可以正常执行。