未绑定通配符泛型在 Java 中的用途和意义是什么?
我不明白未绑定通配符泛型的用途是什么。具有上限的绑定通配符泛型非常有意义,因为使用多态性,我可以处理该类型或集合。但是,拥有可以是任何类型的泛型有什么意义呢?难道它违背了泛型的目的吗?编译器没有发现任何冲突,并且在类型擦除后,就像没有使用泛型一样。<? extends Animal>
我不明白未绑定通配符泛型的用途是什么。具有上限的绑定通配符泛型非常有意义,因为使用多态性,我可以处理该类型或集合。但是,拥有可以是任何类型的泛型有什么意义呢?难道它违背了泛型的目的吗?编译器没有发现任何冲突,并且在类型擦除后,就像没有使用泛型一样。<? extends Animal>
当您的方法并不真正关心实际类型时,未绑定类型可能很有用。
一个原始的例子是这样的:
public void printStuff(Iterable<?> stuff) {
for (Object item : stuff) {
System.out.println(item);
}
}
由于可以处理所有引用类型(通过调用),我们并不关心它的实际内容是什么。PrintStream.println()
toString()
Iterable
并且调用方可以传入 a 或 a 或 a 。List<Number>
Set<String>
Collection<? extends MySpecificObject<SomeType>>
还要注意,根本不使用泛型(使用原始类型调用)会产生完全不同的效果:它使编译器处理整个对象,就好像泛型根本不存在一样。换句话说:不仅类的类型参数被忽略,而且方法上的所有泛型类型参数也被忽略。
另一个重要的区别是,您不能向 添加任何(非)值,但可以将所有对象添加到原始类型:null
Collection<?>
Collection
这不会编译,因为 的类型参数是未知类型(= 通配符 ),因此我们无法提供保证可分配给该类型的值(除了 ,它可分配给所有引用类型)。c
?
null
Collection<?> c = new ArrayList<String>();
c.add("foo"); // compilation error
如果省略 type 参数(即使用原始类型),则可以向集合中添加任何内容:
Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());
请注意,编译器将警告您不要使用原始类型,特别是出于这个原因:它会删除与泛型相关的任何类型检查。
当您需要执行检查时。instanceof
您不能像这样参数化:
Object value;
if (value instanceof List<String>) {
// ...
}
所以你要:
Object value;
if (value instanceof List<?>) {
// ...
}