What is the difference between this method declaration:
这个方法声明的区别是什么?
public static <E extends Number> List<E> process(List<E> nums){
and
和
public static List<Number> process(List<Number> nums){
Where would you use the former?
你会在哪里使用前者?
2 个解决方案
#1
46
The first allows process
of a List<Integer>
, a List<Double>
, etc. The second doesn't.
第一个允许处理列表
Generics in Java are invariant. They're not covariant like arrays.
Java中的泛型是不变量。它们不像数组那样是协变的。
That is, in Java, Double[]
is a subtype of Number[]
, but a List<Double>
is NOT a subtype of List<Number>
. A List<Double>
, however, is a List<? extends Number>
.
也就是说,在Java中,Double[]是Number[]的子类型,但是List
There are good reasons for generics being invariant, but that's also why the extends
and super
type are often necessary for subtyping flexibility.
泛型具有不变性有很好的理由,但这也是为什么扩展和超类型对于子类型灵活性通常是必要的。
See also
-
Java Tutorials/Generics/Subtyping
- Explains why generics invariance is a good thing
- 解释为什么泛型不变性是一件好事
- Java教程/泛型/子类型化解释了为什么泛型不变性是一件好事
-
More fun with wildcards
- Explains some uses of
super
andextends
for bounded wildcards - 解释超级和有界通配符扩展的一些用法
- Explains some uses of
- 通配符的更多乐趣解释了super的一些用法,并扩展了有界通配符
-
Java Generics: What is PECS?
- This discusses the "Producer
extends
Consumersuper
" principle - 论述了“生产者延伸消费者超级”原则
- Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
- 有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
- This discusses the "Producer
- Java泛型:什么是PECS?本文讨论了“生产者扩展消费者超级”原则有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
#2
11
The latter method (the one without <E extends Number>
) will only accept a parameter of exactly type List<Number>
and will it always return a List<Number>
. For example, it will not accept List<Integer>
.
后一种方法(没有
The former method (the one with <E extends Number>
) is a generic method, meaning it can accept different types of List
s and it will return the same type of List
, as long as the List
s are lists of something that extends Number
, e.g. List<Integer>
.
前一种方法(具有
Example:
例子:
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
}
See a similar explanation in the Wildcards chapter in the Generics Lesson in the Java Tutorials:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html
在Java教程的泛型课程中可以看到类似的解释:http://java.sun.com/docs/books/tutorial/java/generics/subtyp.html
See also How to cast a list of inheriting objects to a collection of objects in Java? Both questions are really about generics and subtypes, e.g. whether List<Integer>
is a subtype of List<Number>
(it's not!!!).
请参见如何将继承对象的列表强制转换为Java中的对象集合?这两个问题都是关于泛型和子类型的,例如List
#1
46
The first allows process
of a List<Integer>
, a List<Double>
, etc. The second doesn't.
第一个允许处理列表
Generics in Java are invariant. They're not covariant like arrays.
Java中的泛型是不变量。它们不像数组那样是协变的。
That is, in Java, Double[]
is a subtype of Number[]
, but a List<Double>
is NOT a subtype of List<Number>
. A List<Double>
, however, is a List<? extends Number>
.
也就是说,在Java中,Double[]是Number[]的子类型,但是List
There are good reasons for generics being invariant, but that's also why the extends
and super
type are often necessary for subtyping flexibility.
泛型具有不变性有很好的理由,但这也是为什么扩展和超类型对于子类型灵活性通常是必要的。
See also
-
Java Tutorials/Generics/Subtyping
- Explains why generics invariance is a good thing
- 解释为什么泛型不变性是一件好事
- Java教程/泛型/子类型化解释了为什么泛型不变性是一件好事
-
More fun with wildcards
- Explains some uses of
super
andextends
for bounded wildcards - 解释超级和有界通配符扩展的一些用法
- Explains some uses of
- 通配符的更多乐趣解释了super的一些用法,并扩展了有界通配符
-
Java Generics: What is PECS?
- This discusses the "Producer
extends
Consumersuper
" principle - 论述了“生产者延伸消费者超级”原则
- Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
- 有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
- This discusses the "Producer
- Java泛型:什么是PECS?本文讨论了“生产者扩展消费者超级”原则有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
#2
11
The latter method (the one without <E extends Number>
) will only accept a parameter of exactly type List<Number>
and will it always return a List<Number>
. For example, it will not accept List<Integer>
.
后一种方法(没有
The former method (the one with <E extends Number>
) is a generic method, meaning it can accept different types of List
s and it will return the same type of List
, as long as the List
s are lists of something that extends Number
, e.g. List<Integer>
.
前一种方法(具有
Example:
例子:
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
}
See a similar explanation in the Wildcards chapter in the Generics Lesson in the Java Tutorials:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html
在Java教程的泛型课程中可以看到类似的解释:http://java.sun.com/docs/books/tutorial/java/generics/subtyp.html
See also How to cast a list of inheriting objects to a collection of objects in Java? Both questions are really about generics and subtypes, e.g. whether List<Integer>
is a subtype of List<Number>
(it's not!!!).
请参见如何将继承对象的列表强制转换为Java中的对象集合?这两个问题都是关于泛型和子类型的,例如List