Java 泛型,未绑定通配符 <?> 与 <Object>
Java generics, Unbound wildcards <?> vs <Object>
我已经阅读了一些主题,其中涵盖了有关泛型的某些问题,例如它们的 relationship with raw types. But I'd like an additional explanation on a certain line found in the Java SE tutorial on unbound generics 。
根据一句话:
The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>.
如果我理解这句话; List<?>
和 List<Object>
之间的区别在于,我们可以通过实现前者来使用类型参数 List<String>
或 List<Integer>
。而如果我们实现后者,我们只能使用类型参数 List<Object>
。好像 List<?>
是 Object
的上限,即 List<? extends Object>
.
但是接下来的句子让我感到困惑,因为根据我之前的理解,List<Object>
应该只包含 class Object
的实例,而不是其他东西。
It's important to note that List<Object>
and List<?>
are not the same. You can insert an Object, or any subtype of Object, into a List<Object>
. But you can only insert null
into a List<?>
.
这里有两个不同的问题。 List<Object>
实际上可以像你说的那样接受任何对象。 List<Number>
可以接受 至少 Number
个对象,当然也可以是任何子类,例如 Integer
.
但是这样的方法:
public void print(List<Number> list);
实际上只会取一个List
,正好List<Number>
。它不会采用任何声明为 List<Integer>
.
的列表
所以不同之处在于 List<?>
将采用任何带有任何声明的列表,但 List<Object>
将 仅 采用 声明的内容 与 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>
.[=21= 的超类型]
addObjectToList3
编译和调用都有效。这是将元素添加到通用列表的方法。
我已经阅读了一些主题,其中涵盖了有关泛型的某些问题,例如它们的 relationship with raw types. But I'd like an additional explanation on a certain line found in the Java SE tutorial on unbound generics 。
根据一句话:
The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>.
如果我理解这句话; List<?>
和 List<Object>
之间的区别在于,我们可以通过实现前者来使用类型参数 List<String>
或 List<Integer>
。而如果我们实现后者,我们只能使用类型参数 List<Object>
。好像 List<?>
是 Object
的上限,即 List<? extends Object>
.
但是接下来的句子让我感到困惑,因为根据我之前的理解,List<Object>
应该只包含 class Object
的实例,而不是其他东西。
It's important to note that
List<Object>
andList<?>
are not the same. You can insert an Object, or any subtype of Object, into aList<Object>
. But you can only insertnull
into aList<?>
.
这里有两个不同的问题。 List<Object>
实际上可以像你说的那样接受任何对象。 List<Number>
可以接受 至少 Number
个对象,当然也可以是任何子类,例如 Integer
.
但是这样的方法:
public void print(List<Number> list);
实际上只会取一个List
,正好List<Number>
。它不会采用任何声明为 List<Integer>
.
所以不同之处在于 List<?>
将采用任何带有任何声明的列表,但 List<Object>
将 仅 采用 声明的内容 与 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>
.[=21= 的超类型]
addObjectToList3
编译和调用都有效。这是将元素添加到通用列表的方法。