答案 0 :(得分:2)
您可以很轻松地考虑这一点。 List<? extends SomeClass>
将始终产生SomeClass
的实现。请参见以下示例:
List<Integer> ints = new Arrays.asList(1,2,3,4);
List<? extends Number> nums = ints; // this does work
Integer i = nums.get(0); // this doesn't
Number num = nums.get(0); // this does again
nums.add(5); // this doesn't too
您看到nums
拥有对ints
的引用。因为Integer
扩展了Number
。而且,如果您阅读nums
列表,总会得到Number
。
这对于每个超类-子类关系都适用。
但是:您无法写入nums
列表。也就是说,由于您不完全确切地知道nums
实际引用了哪个列表,在上面的示例中,它是Integer
个列表,因此您只知道会发生什么阅读时从列表中选择。
与List<? super SomeClass>
相同,这与上述内容相反。它将始终使用任何SomeClass
的实现。再次查看示例:
List<Object> objs = new ArrayList<>();
List<? super String> strings = objs; // this does work
strings.add("Some String"); // this works
String string = strings.get(0); // this doesn't
Object object = strings.get(0); // this does again
现在我们只知道类型String
和更具体的每个元素都可以放入Strings
列表中。因为这是上面的反面。如果您尝试阅读列表,则不知道会得到什么。您只能阅读Object
,但永远不会知道它们的实际类别。
通常称为PECS,代表:生产者extends
消费者super
。有关该主题的更多信息,请参见this question