真的需要通配符泛型吗?
例如:
public String add(Set<?> t){
...;
}
public <T> String add(Set<T> t){
...;
}
第一个使用通配符泛型;第二个是泛型方法的正常形式。有什么区别?
在什么情况下我们需要通配符泛型,而不是泛型的正常形式?
例如:
public String add(Set<?> t){
...;
}
public <T> String add(Set<T> t){
...;
}
第一个使用通配符泛型;第二个是泛型方法的正常形式。有什么区别?
在什么情况下我们需要通配符泛型,而不是泛型的正常形式?
下面是需要通配符的情况。此方法采用 ,这是列表的列表。该方法可以将不同组件类型的列表添加到其中:List<List<?>>
public void foo(List<List<?>> t) {
t.add(new ArrayList<String>());
t.add(new ArrayList<Integer>());
}
不能使用不带通配符的泛型类型参数执行此操作。例如,以下操作不起作用:
public <T> void foo(List<List<T>> t) {
t.add(new ArrayList<String>()); // does not compile
t.add(new ArrayList<Integer>()); // does not compile
}
由于添加了对泛型的支持,因此使用参数化类型而不提供类型参数通常会导致编译器警告。另一方面,在某些情况下,您根本不关心类型参数是什么(即您在任何地方都不使用该类型),或者更糟糕的是,您可能根本不知道是什么,而使用可以让您表达出来而不会引起编译器警告。T
<?>
“不在乎”情况的可能用例(为了简洁起见,非常简单,但你明白了):
public void clearList(List<?> list) {
list.clear();
}
“不知道”情况的一个例子:来自类的实际方法签名:Class
static Class<?> forName(String className);
此处,该方法返回某种类型的对象。 是泛型的,但当然你不知道类型,因为它取决于在运行时解析的参数。所以你不能放在这里,因为在编译时是未知的(即使对于特定的调用站点),并且只使用没有type参数将是一个不好的做法,并导致编译器警告。Class
Class
className
T
T
Class