Java 泛型、未绑定通配符<>与<对象>

2022-09-01 10:31:06

我已经阅读了一些主题,这些主题涵盖了有关泛型的某些问题,例如它们与原始类型的关系。但是,我想对Java SE教程中关于未绑定泛型的某一行进行额外的解释。

根据一句话:

printList的目标是打印任何类型的列表,但它未能实现该目标 - 它只打印对象实例的列表;它无法打印 List<Integer>、List<String>、List<Double> 等,因为它们不是 List<Object> 的子类型。

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

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

重要的是要注意这一点,并且不一样。可以将对象或任何子类型对象插入到 .但是您只能插入到 .List<Object>List<?>List<Object>nullList<?>


答案 1

这里有两个独立的问题。A实际上可以像你说的那样接受任何物体。A 至少可以接受对象,当然也可以采用任何子类,例如 .List<Object>List<Number>NumberInteger

但是像这样的方法:

public void print(List<Number> list);

实际上只会采取一个确切的.它不会采用任何声明的列表。ListList<Number>List<Integer>

因此,不同之处在于将采用任何声明的任何列表,但只会采用声明为,没有别的。List<?>List<Object>List<Object>

最后一句话只是简单地说,这是一个列表,你真的不知道它的项目是什么类型。因此,除了 之外,您无法向其添加任何内容。List<?>null


答案 2

令人困惑的句子试图警告您,虽然是所有泛型列表的超类型,但您无法向集合添加任何内容。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不编译,因为除了添加到 .(这就是这句话想告诉你的。nullList<?>

addObjectToList2编译,但对它的调用不会编译,因为 不是 的超类型。main()List<Object>List<String>

addObjectToList3编译和调用都有效。这是向泛型列表添加元素的方法。


推荐