我不明白未绑定的通配符泛型的用途是什么。具有上边界<? extends Animal>
的绑定通配符泛型非常有意义,因为使用多态性我可以使用该类型或集合。但是具有任何类型的泛型有什么意义呢?它不会破坏仿制药的目的吗?编译器没有发现任何冲突,在类型擦除后,就像没有使用泛型一样。
答案 0 :(得分:27)
当您的方法并不真正关心实际类型时,未绑定类型会很有用。
一个原始的例子是:
public void printStuff(Iterable<?> stuff) {
for (Object item : stuff) {
System.out.println(item);
}
}
由于PrintStream.println()
可以处理所有引用类型(通过调用toString()
),我们不会关注 Iterable
的实际内容。< / p>
来电者可以传入List<Number>
或Set<String>
或Collection<? extends MySpecificObject<SomeType>>
。
另请注意,不使用泛型(使用原始类型调用)会产生完全不同的效果:它使编译器处理整个对象,就好像泛型不存在于所有。换句话说:不仅忽略了类的类型参数,还忽略了方法上的所有泛型类型参数。
另一个重要的区别是,您无法向null
添加任何(非Collection<?>
)值,但可以将所有对象添加到原始类型{{ 1}}:
这将无法编译,因为Collection
的类型参数是未知类型(=通配符c
),因此我们无法提供保证可分配给它的值(?
除外,可分配给所有引用类型)。
null
如果你保留type参数(即使用原始类型),那么你可以将任何添加到集合中:
Collection<?> c = new ArrayList<String>();
c.add("foo"); // compilation error
请注意,编译器警告您不要使用原始类型,特别是出于这个原因:它删除了与泛型相关的任何类型检查。
答案 1 :(得分:6)
当您需要执行instanceof
检查时。
您无法像这样进行参数化:
Object value;
if (value instanceof List<String>) {
// ...
}
所以你这样做:
Object value;
if (value instanceof List<?>) {
// ...
}
答案 2 :(得分:2)
对于未绑定的通配符,有(罕见的)完全正确的用例。 SDK包含其中一些。
一个示例是一种对任何类型的列表执行明确操作的方法,并且不会在rotate
中返回任何Collections
的内容:
static void rotate(List<?> list, int distance)
另一个例子是当你想列出一个类的可能构造函数时,方法是:
Constructor<?>[] getConstructors()
这里甚至不可能使用泛型,因为根据定义,数组将包含不同的构造函数,每个构造函数都有自己的实际类。相比之下,API确实使用通用签名来获取一个构造函数:Constructor<T> getConstructor(Class<?>... parameterTypes)
。
结论是,即使它主要用于与旧代码的兼容性,仍然存在未绑定的通配符泛型是正确的方法。
答案 3 :(得分:1)
虽然使用原始类型意味着你不了解泛型(因为你很懒或很久以前写过代码),使用<?>
意味着你了解泛型并明确强调你的代码可以工作与任何类型的对象。
答案 4 :(得分:1)
请允许我重新解释一下这个问题:
“List<Object>
和List<?>
之间有什么区别?”
答案是List<?>
限制性更强。它告诉我们,我们有一堆某种类型的对象,但该类型不一定是Object
。
由于我们不知道该类型是什么,我们无法添加到列表中 - 我们添加的任何内容都可能是错误的类型。事实上,我们不能将?
类型的任何参数传递给任何方法,而不仅仅是add()
。
从好的方面来说,当我们指定方法需要List<?>
时,可以使用List<String>
或List<Integer>
或任何其他List<>
。 List<Object>
只能List<Object>
。
答案 5 :(得分:0)
使用无界通配符只有在包装不使用泛型的旧代码时才有意义,AFAIK,基本上是集合。
如果你看看你能用这种通用做什么,它基本上是 nothing 。
如果你有一个集合你不能添加任何东西,如果你试着读一些东西,你总会得到Object
等等。
这反过来有助于保证您将以类型安全的方式处理数据,而使用原始类型会导致编译器忽略您所做的任何混乱。
来自Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type?的{p> Angelika Langers Java Generics FAQ可能会引起人们的兴趣。