Java泛型,未绑定的通配符<! - ? - > vs <object>

时间:2016-02-08 15:10:07

标签: java generics wildcard

我已经阅读了一些主题,其中涵盖了有关泛型的某些问题,例如relationship with raw types。但我想对 Java SE tutorial on unbound generics 中找到的某一行进行补充说明。

根据一句话:

  

printList的目标是打印任何类型的列表,但它无法实现该目标 - 它只打印一个Object实例列表;它无法打印List&lt; Integer&gt;,List&lt; String&gt;,List&lt; Double&gt;等等,因为它们不是List&lt; Object&gt;的子类型。

如果我理解这句话; List<?>List<Object>之间的区别在于我们可以通过实现前者来使用类型参数List<String>List<Integer>。如果我们实现后者,我们只能使用类型参数List<Object>。好像List<?>Object的上限,即List<? Object>

但接下来的句子让我感到困惑,因为根据我之前的理解,List<Object>应该只包含类Object的实例,而不包含其他内容。

  

重要的是要注意List<Object>List<?>不一样。您可以将对象或Object的任何子类型插入List<Object>。但您只能将null插入List<?>

2 个答案:

答案 0 :(得分:15)

这里有两个不同的问题。事实上List<Object>可以像你说的那样接受任何对象。 List<Number>可以使用至少 Number个对象,当然也可以使用任何子类,例如Integer

然而,这样的方法:

public void print(List<Number> list);

实际上只会 采用完全 List的{​​{1}}。它不会采用任何声明为List<Number>的列表。

所以区别在于List<Integer>会将任何列表与任何声明相关联,但List<?>只会 声明的内容视为{{ 1}},别的。

最后一句话简单地指出,List<Object>是一个列表,您根本不知道其项目的类型。因此,除了List<Object>之外,您无法向其中添加任何内容。

答案 1 :(得分:8)

令您困惑的句子是试图警告您,虽然List<?>是所有通用列表的超类型,但您无法向List<?>集合添加任何内容。

假设您尝试了以下代码:

private static void addObjectToList1(final List<?> aList, final Object o ) {
    aList.add(o);
}

private static void addObjectToList2(final List<Object> aList, final Object o ) {
    aList.add(o);
}

private static <T> void addObjectToList3(final List<T> aList, final T o ) {
    aList.add(o);
}


public static void main(String[] args) {
    List<String> testList = new ArrayList<String>();
    String s = "Add me!";
    addObjectToList1(testList, s);
    addObjectToList2(testList, s);
    addObjectToList3(testList, s);
}

addObjectToList1无法编译,因为您无法将除null之外的任何内容添加到List<?>。 (那是句子试图告诉你的内容。)

addObjectToList2已编译,但main()中对其的调用无法编译,因为List<Object>不是List<String>的超类型。

addObjectToList3编译和调用都有效。这是将元素添加到通用列表的方法。