这个方法声明的区别是什么:
public static <E extends Number> List<E> process(List<E> nums){
并且
public static List<Number> process(List<Number> nums){
你会在哪里使用前者?
第一个允许处理List<Integer>
、List<Double>
等类型的process
,而第二个则不行。
Java中的泛型是不变的。它们不像数组一样是协变的。
也就是说,在Java中,Double[]
是Number[]
的子类型,但是List<Double>
不是List<Number>
的子类型。然而,List<Double>
是List<? extends Number>
的子类型。
有很好的理由让泛型保持不变,但这也是为什么extends
和super
类型经常需要用于子类型灵活性的原因。
super
和extends
的用途extends
消费者super
"原则<E extends Number>
)只接受完全类型为List<Number>
的参数,并且它始终返回List<Number>
。例如,它将不会接受List<Integer>
。
前一种方法(带有<E extends Number>
)是一种泛型方法,意味着它可以接受不同类型的List
并且它将返回相同类型的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教程的泛型课程中的通配符章节中,可以看到类似的解释:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html
同时,也可以参考如何将一组继承对象强制转换为Java中对象的集合?。这两个问题都涉及到泛型和子类型,例如 List<Integer>
是否是 List<Number>
的子类型(它不是!)。
<E extends Number> E process(E elt)
和Number process(Number elt)
。 - Vic Seedoubleyew