泛型类型和通配符类型的区别 [英] Difference between generic type and wildcard type
问题描述
我是 Generic 的新手,我的问题是:两个函数之间有什么区别:
I'm a newbie in Generic and my question is: what difference between two functions:
功能一:
public static <E> void funct1 (List<E> list1) {
}
功能2:
public static void funct2(List<?> list) {
}
推荐答案
第一个签名说:list1 是一个 Es 列表.
The first signature says: list1 is a List of Es.
第二个签名表示:list 是某种类型的实例列表,但我们不知道类型.
The second signature says: list is a List of instances of some type, but we don't know the type.
当我们尝试更改方法时,差异变得很明显,因此它需要第二个参数,应该将其添加到方法内的列表中:
The difference becomes obvious when we try to change the method so it takes a second argument, which should be added to the list inside the method:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
第一个效果很好.并且您不能将第二个参数更改为实际可以编译的任何内容.
The first one works nicely. And you can't change the second argument into anything that will actually compile.
实际上我刚刚找到了一个更好的差异演示:
Actually I just found an even nicer demonstration of the difference:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
人们可能会问为什么我们需要 <?>
,因为它只限制了我们可以用它做什么(就像@Babu_Reddy_H 在评论中所做的那样).我看到通配符版本的以下好处:
One might as why do we need <?>
when it only restricts what we can do with it (as @Babu_Reddy_H did in the comments). I see the following benefits of the wildcard version:
调用者不必知道他传入的对象.例如,如果我有一个列表映射:
Map
我可以通过它的值给你的函数,而不指定列表元素的类型.所以
The caller has to know less about the object he passes in. For example if I have a Map of Lists:
Map<String, List<?>>
I can pass its values to your function without specifying the type of the list elements. So
如果我分发像这样参数化的对象,我会主动限制人们对这些对象的了解以及他们可以用它做什么(只要他们远离不安全的投射).
If I hand out objects parameterized like this I actively limit what people know about these objects and what they can do with it (as long as they stay away from unsafe casting).
当我将它们组合起来时,这两个是有意义的:List
.例如,考虑一个方法 List
,将两个输入列表合并为一个新的结果列表.当然你可以再引入两个类型参数,但你为什么要这么做?这将结束指定的事情.
These two make sense when I combine them: List<? extends T>
. For example consider a method List<T> merge(List<? extends T>, List<? extends T>)
, which merges the two input lists to a new result list. Sure you could introduce two more type parameters, but why would you want to? It would be over specifying things.
- 最后通配符可以有下限,所以使用列表可以使
add
方法起作用,而get
不会给你任何有用的东西.这当然会引发下一个问题:为什么泛型没有下界?
- finally wildcards can have lower bounds, so with lists you can make the
add
method work, whileget
doesn't give you anything useful. Of course that triggers the next question: why don't generics have lower bounds?
有关更深入的答案,请参阅:何时使用泛型方法以及何时使用通配符? 和 http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
For a more in depth answer see: When to use generic methods and when to use wild-card? and http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
这篇关于泛型类型和通配符类型的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!