Java 泛型,未绑定通配符 <?> vs <Object>

问题描述 投票:0回答:2

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

根据一句话:

printList 的目标是打印任何类型的列表,但它未能实现该目标——它仅打印 Object 实例的列表;它不能打印 List、List、List 等,因为它们不是 List 的子类型。

如果我理解这句话;

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

但是接下来的句子让我感到困惑,因为根据我之前的理解,

List<Object>
应该只包含类
Object
的实例而不是其他东西。

需要注意的是

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

这里有两个独立的问题。

List<Object>
实际上可以像你说的那样接受任何对象。一个
List<Number>
可以带至少
Number
对象,或者当然可以带任何子类,比如
Integer
.

但是这样的方法:

public void print(List<Number> list);

实际上需要一个

List
这是exactly
List<Number>
。它不会采用任何已声明的列表
List<Integer>
.

所以不同之处在于

List<?>
将采用任何带有任何声明的列表,但是
List<Object>
onlydeclared 的内容作为
List<Object>
,没有别的。

最后一个引述简单地说,

List<?>
是一个列表,您实际上不知道它的项目是什么类型。因此,除了
null
之外,您不能添加任何东西。

让您感到困惑的句子试图警告您,虽然

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
编译和调用都有效。这是将元素添加到通用列表的方法。

java generics wildcard
2个回答
44
投票

这里有两个独立的问题。

List<Object>
实际上可以像你说的那样接受任何对象。一个
List<Number>
可以带至少
Number
对象,或者当然可以带任何子类,比如
Integer
.

但是这样的方法:

public void print(List<Number> list);

实际上需要一个

List
这是exactly
List<Number>
。它不会采用任何已声明的列表
List<Integer>
.

所以不同之处在于

List<?>
将采用任何带有任何声明的列表,但是
List<Object>
onlydeclared 的内容作为
List<Object>
,没有别的。

最后一个引述简单地说,

List<?>
是一个列表,您实际上不知道它的项目是什么类型。因此,除了
null
之外,您不能添加任何东西。


21
投票

让您感到困惑的句子试图警告您,虽然

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
编译和调用都有效。这是将元素添加到通用列表的方法。

© www.soinside.com 2019 - 2024. All rights reserved.