我通常不喜欢使用通配符。这些是选项:
使用列表是针对未知类型的列表:
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 阅读更多相关信息。