33

我正在阅读有关泛型的信息,但我不明白对未绑定通配符的需求以及它与原始类型的区别。我读了这个问题,但仍然没有弄清楚。在 未绑定通配符的 Java 教程页面中,我得到以下两点,但我不明白第一点:

  • 如果您正在编写一个可以使用Object类中提供的功能来实现的方法。
  • 当代码使用泛型类中不依赖于类型参数的方法时。例如,List.size()List.clear()。事实上,Class<?>之所以经常使用,是因为其中的大多数方法Class<T>都不依赖于T.

有人可以用外行语言解释未绑定通配符和原始类型之间的区别。

与有何List<?>不同?List<Object>

4

5 回答 5

43

有何List<?>不同List<Object>

主要区别在于第一行编译但第二行不编译:

List<?> list = new ArrayList<String> ();
List<Object> list = new ArrayList<String> ();

但是,因为你不知道泛型类型List<?>是什么,所以你不能使用它的参数化方法:

List<?> list = new ArrayList<String> ();
list.add("aString"); //does not compile - we don't know it is a List<String>
list.clear(); //this is fine, does not depend on the generic parameter type

至于与原始类型(无泛型)的区别,下面的代码编译并运行良好:

List list = new ArrayList<String> ();
list.add("aString");
list.add(10);
于 2013-01-09T16:50:25.163 回答
5

有何List<?>不同?List<Object>

    List<Object> l1 = new ArrayList();
    List<?> l2 = new ArrayList();
    l1.add("Object");
    //l2.add("Object");   incorrect
    l2.add(null);

您只能将空值添加到List<?>

于 2013-01-09T17:27:29.603 回答
4

就个人而言,我发现Java 通配符教程中的这个附加链接很有帮助。

List<?>我看到和之间的主要区别List之一是前者只能用于从它的元素中读取(除非你真的想添加null),后者允许(未经检查)向它添加任意类型的对象,可能是意外的一面 -效果。

于 2014-02-10T20:54:47.883 回答
4

有人可以用外行语言解释未绑定通配符和原始类型之间的区别。

未绑定的通配符类型可以保持集合的类型不变,而原始类型不能。正如 Joshua Bloch 在他的Effective Java中所说,

您可以将任何元素放入具有原始类型的集合中,这很容易破坏集合的类型不变量(如第 112 页上的 unsafeAdd 方法所示);您不能将任何元素(除了 null)放入 Collection<?>。

因此,只要您将参数化类型列表分配给未绑定通配符类型列表,集合的类型不变性将保持不变。

List<String> list1 = new ArrayList();
list1.add("foo");
list1.add("bar");
List<?> list2 = list1;

如果您分配一个原始类型列表,其元素属于不同类型,则未绑定的通配符类型将不会保持集合的类型 invariant,因为该列表最初是变体类型。

List list1 = new ArrayList();
list1.add(1);
list1.add("foo");
List<?> list2 = list1;
于 2018-06-12T09:44:11.443 回答
2

List 在方法签名中非常有用,可以调用从不需要类型参数的方法,例如,从列表中读取或旋转它。

void someMethod(List<?> list) {
  list.clear();  // I will never add anything to the list in here
}

您将永远不会添加任何内容或以其他方式修改列表所包含的类型,因为您不能将任何内容添加到列表中,除了具有此签名的方法中的 null 之外,因此您永远不会破坏类型安全。另一方面,原始列表可以做任何事情,众所周知,这会导致类型安全违规。

void someMethod2(List list) {
 list.add(new WeaselFurBrush());  
}
List list1 = new ArrayList<String>();
someMethod2(list1);// oops
于 2015-10-28T21:39:11.457 回答