为什么我们需要 Java 中的纯 <?>?

why do we need the pure <?> in Java?

为什么我们需要 Java 中的纯 <?>? 传递的任何东西都只能用作 Object 吗?所以它与任何 class 转换为 Object 一样有用(只有 9 种方法可用)

谢谢


我的意思是,如果你有 List< ? > 列表,您只能将项目用作对象。这意味着 list.get(0) 给你对象,仅此而已。是的,我也可以在那里存储任何东西,但是它对你有用吗?这就像你有一件好东西,一件昂贵的东西,却把它扔进了垃圾桶。你只能从垃圾桶里得到垃圾。同样,您可以将任何 class 的任何好对象放入 List,但仅使用 9 种方法从那里获取对象。

无界通配符在两种情况下是一种有用的方法:

  • 如果您编写的方法可以使用 Object class 中提供的功能来实现。

  • 当代码使用不依赖于类型参数的泛型 class 中的方法时。
    例如,List.size,或 List.clear。事实上,Class<?> 之所以如此常用,是因为 Class<T> 中的大多数方法都不依赖于 T.

例如见Collections.swap方法:

public static void swap(List<?> list, int i, int j) {
    final List l = list;
    l.set(i, l.set(j, l.get(i)));
}

知道类型无助于交换 List 中的两个元素,因此使用了无限通配符。您传入一个 List - 任何 List - 该方法交换索引元素。无需担心类型参数。

有关详细信息,请参阅:Unbounded Wildcards.

我认为最好的答案是因为有时你根本不知道 class 参数化的类型。正如迈克尔指出的那样 List<?>List<Object> 不同。所以?提供了不同的语义,这对保证程序的正确性很有用。

考虑两个列表。一个列表是 List<String>,另一个是 List<Integer>。两者都是 Object,但我们仍然不想将它们混淆。我们不想将 String 放入 Integer 列表中,反之亦然。所以如果你有一个声明为 List<?> 的类型,你就不能安全地将任何类型放入该列表中。 ? 可能是 StringInteger,但您不知道它是什么,而且您不想混淆它们,所以您不能输入任何一个。

OTOH,List<Object> 只是一个对象列表,因为您声明它包含任何对象,所以您可以安全地将 StringInteger 都放在列表中。你说你不关心通过声明类型 Object 进入列表的内容,所以任何类型都可以。在我能想到的任何有意义的方式中,List<Object> 都等同于原始类型。这是一个您自己管理的列表,无需编译器的帮助。