以下应用程序产生编译错误行(*)
ArrayList<?> l = new ArrayList<>();
l.add(new Integer(1));
编译错误说:
error: no suitable method found for add(C<CAP#1>)
l.add(o);
这是为什么?我以为List应该接受任何东西
你误解了List<?>
的含义。
它并不意味着:任何类型物体的List
,所以你应该能够添加任何东西到List
(它与原始的List
或List<Object>
不同)。
它意味着:一种特定但未知类型的List
。因为类型是未知的,所以你不能在列表中添加任何内容 - 编译器不知道列表中对象的确切类型应该是什么,所以它无法检查你是否没有尝试将某些内容添加到列表中不应该被允许,因此它不允许您向列表中添加任何内容。
我通常不喜欢使用通配符。这些是选项:
使用List是针对具有未知类型的列表:
List<?> list = Arrays.asList(1, 2d, "3"); // can contain any Object
for (Object obj : list) { // you can retrieve them
System.out.println("--> " + obj);
}
list.add("a"); // compile error
使用<? extends Number>
可以从列表中检索数字,但仍然无法添加任何内容:
List<? extends Number> list2 = Arrays.asList(1, 2, 3); // can contain any number
for (Number n : list2) {
System.out.println("--> " + n);
}
list2.add(5); // compile error
List<? extends Number> list3 = Arrays.asList(1, 2d, 3F); // can contain any number
for (Number n : list3) {
System.out.println("--> " + n);
}
list3.add(5); // compile error
与<? extends ...>
相反的是<? super ...>
。这看起来很奇怪。关键是这种List<>
的调用者可以添加适当类型的东西。但检索是一个问题:
List<? super Integer> list4 = new ArrayList<>();
list4.add(1);
for (Integer num : list4) { } // compile error
for (Object num : list4) { } // this is fine, but not that useful
如果您需要灵活的数据结构,可以使用正确的超类型。比方说,List<Number>
非常灵活。如果你真的需要,你可以使用绑定类型,如List<T extends Number>
。您可以在this answer上阅读更多相关信息。