List<Number>和List<? extends Number>有什么区别?

9

关于Java泛型,我有一个非常基础的问题。我认为List<Number>List<? extends Number>都是同质的。我是对的还是我忽略了什么基本的东西?

3个回答

6

通用类型更加严谨。

<? extends Number> 表示 Number 或其未知的子类。如果您获得这样一个值,它将是一个 Number,但您不能赋值这种类型的值,因为您不知道哪个值是有效的。

区别在于参数和返回值。

List<Number> numbers = new ArrayList<Number>();
Number n = 1;
numbers.add(n); // ok.
n = numbers.get(0); // ok
numbers.add(1); // ok.

List<? extends Number> numbers2 = new ArrayList<Double>();
numbers2.add(n); // not ok
n = numbers2.get(0); // ok

List<? super Number> numbers3 = new ArrayList<Serializable>();
numbers3.add(n); // ok
n = numbers3.get(0); // not ok.

super在一些情况下用于表示类型可以是超级类型。例如:

在Collections中,此方法表示Comparator需要能够比较相同类型或任何超级类型。

public static <T> void sort(List<T> list, Comparator<? super T> c)

这意味着您可以拥有:
Comparator<Number> comparesAnyNumbers = ...
List<Integer> ints = ...
Collections.sort(ints, comparesAnyNumbers);

它们更加具体,<Number> 意味着仅仅是数字类型而不包括其他类型。 - Peter Lawrey
1
在我看来,它并不是非常有用。 ;) - Peter Lawrey
@Nandkumar 不是的,numbers2 实际上是一个 ArrayList<Double> - Peter Lawrey
1
从编译器的角度来看,number2 是一个 List<? extends Number> 而不是一个 ArrayList<Double>。指令 numbers2.add(Double.valueOf(1d)); 也无法工作。 - gontard
1
@PeterLawrey 在 List<? extends Number> 中无法添加任何东西(除了 null)? - gontard
显示剩余10条评论

3

泛型是编译时语言功能,这意味着它们不存在于运行时。在泛型机制中,为了进行编译时检查,它们不是同种类型的,即如果想在泛型类型中使用多态性。

下面的代码看似合法,但实际上会导致编译时错误:

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

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

是有效的。此外,您不能在右侧使用通配符类型:

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

无法编译。


1

List<Number> --> Number列表(或Number实例的列表)

List<? extends Number> --> 列出任何扩展Number类型的列表


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接