<E extends Number>和<Number>之间有什么区别?

这个方法声明有什么区别:

public static <E extends Number> List<E> process(List<E> nums){ 

  public static List<Number> process(List<Number> nums){ 

你会在哪里使用前者?

第一个允许List<Integer>List<Double>等的过程。第二个不允许。

Java中的generics是不变的。 它们不像数组一样协变。

也就是说,在Java中, Double[]Number[]的子types,但List<Double>不是List<Number>的子types。 List<Double>List<? extends Number> List<? extends Number>

generics是不变的,这也是很好的原因,但这也是为什么extendssupertypes常常是子types灵活性所必需的。

也可以看看

  • Java教程/generics/子types
    • 解释为什么generics不变是一件好事
  • 通配符更有趣
    • 解释了super一些用法,并extends了有界的通配符
  • Javagenerics:什么是PECS?
    • 这里讨论“生产者extends消费者super ”的原则
    • Effective Java第2版 ,第28项:使用有界通配符来增加API的灵活性

后一种方法没有 <E extends Number> )只接受一个List<Number>types的参数,并且总是返回一个List<Number> 。 例如,它不会接受List<Integer>

前一种方法带有 <E extends Number> 方法 )是一个通用的方法 ,这意味着它可以接受不同types的List ,并且它将返回相同types的List ,只要List一些扩展Number ,例如List<Integer>

例:

 import java.util.ArrayList; import java.util.List; public class ProcessGenerics { List<Number> listNumber = new ArrayList<Number>(); List<Integer> listInteger = new ArrayList<Integer>(); List<Double> listDouble = new ArrayList<Double>(); public static List<Number> processWithoutExtends(List<Number> nums){ return nums; } List<Number> resultN = processWithoutExtends(listNumber); // OK //List<Integer> resultI = processWithoutExtends(listInteger); // compile-error - method not applicable //List<Double> resultD = processWithoutExtends(listDouble); // compile-error - method not applicable public static <E extends Number> List<E> processWithExtends(List<E> nums){ return nums; } List<Number> resultN2 = processWithExtends(listNumber); // OK List<Integer> resultI2 = processWithExtends(listInteger); // OK List<Double> resultD2 = processWithExtends(listDouble); // OK } 

在Java教程的generics课程的通配符一章中看到类似的解释:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html

另请参见如何将inheritance对象的列表转换为Java中的对象集合? 这两个问题都是关于generics和子types,例如List<Integer>List<Number>的子types(不是!!!)。