Java中未绑定的通配符泛型的用途和要点是什么?

lis*_*sak 26 java generics wildcard

我不明白未绑定的通配符泛型的用途是什么.带有上边界的绑定通配符泛型<? extends Animal>非常有意义,因为使用多态性我可以使用该类型或集合.但是具有任何类型的泛型有什么意义呢?它不会破坏仿制药的目的吗?编译器没有发现任何冲突,在类型擦除之后,就像没有使用泛型一样.

Joa*_*uer 27

当您的方法不关心实际类型时,未绑定类型可能很有用.

一个原始的例子是这样的:

public void printStuff(Iterable<?> stuff) {
  for (Object item : stuff) {
    System.out.println(item);
  }
}
Run Code Online (Sandbox Code Playgroud)

既然PrintStream.println()可以处理所有引用类型(通过调用toString()),我们不关心它的实际内容Iterable是什么.

并且来电者可以通过a List<Number>或a Set<String>或a Collection<? extends MySpecificObject<SomeType>>.

另请注意,不使用泛型(使用原始类型调用)会产生完全不同的效果:它使编译器处理整个对象,就好像泛型根本不存在一样.换句话说:不仅忽略类的类型参数,还忽略方法上的所有泛型类型参数.

另一个重要的区别是您不能null向a 添加任何(非)值Collection<?>,但可以将所有对象添加到原始类型Collection:

这将无法编译,因为类型参数c是未知类型(=通配符?),因此我们无法提供保证可分配给它的值(除了null可分配给所有引用类型的值).

Collection<?> c = new ArrayList<String>();
c.add("foo");    // compilation error
Run Code Online (Sandbox Code Playgroud)

如果将类型参数保留(即使用原始类型),则可以向集合中添加任何内容:

Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());
Run Code Online (Sandbox Code Playgroud)

请注意,编译器将警告您不要使用原始类型,特别是出于这个原因:它删除与泛型相关的任何类型检查.

  • 但我的问题是:为什么要使用泛型呢?它可以是"Iterable stuff"......使用通配符毫无意义 (4认同)
  • @Edgar:`?`不仅仅意味着"我不在乎".它的意思是"某种特定类型,但我不知道哪一种".如果您尝试添加`String`,那么编译器会询问"是`String`可分配给我的类型参数"?如果type参数是`Object`或`String`,那么答案是"yes".如果类型参数是"某些特定类型,但我不知道哪一个",那么答案是"我不知道!" 这将被视为"不". (4认同)
  • 我明白了,这很难解释,但我现在完全明白它的目的。很长一段时间以来,我一直在直观地使用通配符,甚至没有考虑太多……谢谢 (2认同)

Fra*_*ani 6

当您需要执行instanceof检查时.

你不能像这样参数化:

Object value;
if (value instanceof List<String>) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

所以你也是:

Object value;
if (value instanceof List<?>) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)