15

这是我的程序。我不确定为什么会出现编译时错误。

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
    List< ? extends Number > list = new ArrayList<Integer>();

    list.add(6); // Compile Time Error

    System.out.println(list);

  }
}

但是以下程序可以正常工作

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
    List< ? super Number > list = new ArrayList<Number>();

    list.add(6); 

    System.out.println(list);

    }
}

来自 Eclipse 的错误:

这是来自 Eclipse 的错误描述:

List 类型中的方法 add(int, capture#1-of ? extends Number) 不适用于参数 (int)

4

4 回答 4

18

这是因为您在第一种情况下所做的不是 type safe。您已声明listList“某个子类Number”的一个,然后尝试将一个Integer插入其中。绝对不能保证Integer与底层列表的实际运行时类型兼容。编译器在这里阻止你,因为你所做的没有任何意义

考虑,作为一个极端的例子:

List< ? extends Object > list = new ArrayList<Integer>();
list.add("Hello, World!");

如果这行得通,你就会有一个List<Integer>with a String

如果你真的想让它工作,你必须通过强制转换告诉编译器你知道你在做什么:

((List<Integer>)list).add(6);

但即便如此,您仍然会收到有关类型安全的警告。

第二种情况有效,因为该列表保证是“数字的某个超类”。Integer是 的子类Number,因此它可以隐式转换为任何超类(包括Number它自己),因此不存在值与列表的实际类型不兼容的风险。

有关更多信息,您可能需要阅读covariance 和 contravariance之间的区别。

于 2012-09-24T14:36:30.290 回答
4

您不能向Lista? extends ...作为其泛型类型的一部分添加任何内容。

让我们看看这个:

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

请注意,List您实际使用的是ArrayList<Integer>. 应该不可能在此列表中放置其他不是Integer. 然而,该类型List<? extends Number>将允许您将例如 a 添加Double到列表中,因为Double也可以 extends Number

有关更多详细信息,请参阅 Angelika Langer 的 Java 泛型常见问题解答中的以下内容:哪些方法和字段可通过通配符参数化类型的引用变量访问/不可访问?

于 2012-09-24T14:38:30.647 回答
1

它关于superextends。比较这个问题

您也可以通过Wildcards查找它。

于 2012-09-24T14:36:46.217 回答
0

这不起作用:

List< ? extends Number > list = new ArrayList<Integer>();
list.add(6); // Compile Time Error

因为如果这样做,您可能会遇到这样的情况。

class Apple extends Number  {}

List< ? extends Number > list = new ArrayList<Integer>();
list.add(new Apple()); //if it were to work, you'd have apples in what you'd think was a list of integers
于 2012-09-24T14:46:32.640 回答