我已经阅读了一些主题,其中涵盖了有关泛型的某些问题,例如relationship with raw types。但我想对 Java SE tutorial on unbound generics 中找到的某一行进行补充说明。
根据一句话:
printList的目标是打印任何类型的列表,但它无法实现该目标 - 它只打印一个Object实例列表;它无法打印List< Integer>,List< String>,List< Double>等等,因为它们不是List< Object>的子类型。
如果我理解这句话; List<?>
和List<Object>
之间的区别在于我们可以通过实现前者来使用类型参数List<String>
或List<Integer>
。如果我们实现后者,我们只能使用类型参数List<Object>
。好像List<?>
是Object
的上限,即List<? Object>
。
但接下来的句子让我感到困惑,因为根据我之前的理解,List<Object>
应该只包含类Object
的实例,而不包含其他内容。
重要的是要注意
List<Object>
和List<?>
不一样。您可以将对象或Object的任何子类型插入List<Object>
。但您只能将null
插入List<?>
。
答案 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
编译和调用都有效。这是将元素添加到通用列表的方法。