用于 '?延伸'和'?超级“在集合泛型 [英] Use of '? extends ' and '? super ' in Collection generics
问题描述
任何人都可以解释为什么我们使用?
Can anybody explain why we use ? in Collection generics.
例如:
List<? extends Number> numberlist;
List<? super Integer> numberlist;
推荐答案
通配符对如何使用集合。
The wildcards introduce restrictions in how the collection can be used.
例如,使用 List < extends Number>
,我无法向列表中添加新元素。这是因为我知道的是,该列表是 Number
的某种子类型,但我不知道什么是实际的子类型(所以我怎么知道什么加?)。例如,请使用以下代码:
For example, with List<? extends Number>
, I can't add new elements to the list. This is because all I know is that the list is some kind of subtype of Number
, but I don't know what that actual subtype is (so how could I know what to add?). For example, take the following code:
public void doSomethingWith(List<? extends Number> numbers) {
numbers.add(Integer.valueOf(0)); // Won't compile
}
>这些方法调用是合法的:
This won't compile because both of these method calls are legal:
doSomethingWith(new ArrayList<Integer>());
doSomethingWith(new ArrayList<Double>());
您可以 从列表中:
// This will all compile
public void doSomethingWith(List<? extends Number> numbers) {
for (Number number : numbers) {
// Do something with number
}
// OR
Number number = numbers.get(0);
// OR
Number number = numbers.remove(0);
}
调用 get
将返回某种类型的 Number
,我们知道因为的事实?
Calls to methods like get
will return some kind of Number
, we know that for a fact because of the ? extends Number
, so we can treat it like that for reading purposes.
另一方面, List
?
是,它肯定会是一个超类 Integer
,所以列表的具体类型肯定会接受 Integer
值。例如:
On the other hand, List<? super Integer>
has exactly the opposite result. I can no longer read from the list, but I can write to it. I know that whatever ?
is, it will definitely be a super-class of Integer
, so concrete types of the list will definitely accept Integer
values. For example:
public void doSomethingWith(List<? super Integer> integers) {
integers.add(Integer.valueOf(0));
}
这段代码是完全合法的。但是,如果你想从列表中读取,唯一的方法是使用 Object
,因为任何东西都需要转换(这需要知道它的具体类型):
That code is completely legal. However, if you want to read from the list, the only way to do this is to use Object
since anything else requires casting (which requires knowing its concrete type):
for (Object obj : integers)
// OR
Object obj = integers.get(0);
// OR
Object obj = integers.remove(0);
真正发生的事
这里是实际发生的事情。当您指定? extends Number
,您正在使用任何以作为参数的元素无法使用的方法。事实上,如果你尝试在Eclipse中使用Ctrl + Space在 List< ;?上自动完成代码extends Number>
,它显示 null
作为 add
方法中的参数类型,类似。同时,元素的所有方法都保证返回至少某种 Number
,虽然你不知道哪个子类的 Number
它可能实际上是
Here's what's actually happening. When you specify ? extends Number
, you're making any method that takes elements as a parameter unusable. In fact, if you try to auto-complete code in Eclipse using Ctrl+Space on a List<? extends Number>
, it shows null
as the parameters' types in the add
methods and the like. Meanwhile, all the methods that return elements are guaranteed to return at least some kind of Number
, though you won't know exactly which subclass of Number
it might actually be.
当你指定? super Integer
,您正在使用任何元素作为参数的方法,保证它们将接受 Integer
值(以及 Integer
的子类)。这允许你调用 add
的方法,因为你知道他们会接受 Integer
类型。同时,所有返回元素的方法只能保证返回 ,但是我们不知道什么,所以返回元素的所有方法只能保证返回对象
。
When you specify ? super Integer
, you're making any method that takes elements as a parameter guarantee that they'll accept Integer
values (and sub-classes of Integer
as well). This allows you to call methods like add
since you know they'll accept Integer
types. Meanwhile, all methods that return elements are only guaranteed to return something, but we don't know what, so all the methods that return elements are only guaranteed to return Object
.
PECS是一个很好的首字母缩写,记住这一点,它意味着 b> E xtends, C onsumer S upers。这意味着如果你想让你的列表给你一些东西,它是一个生产者,你应该使用 extends
。如果你希望你的列表接受你的东西,它是一个消费者,所以你使用 super
。有关详情,请参见此答案。
PECS is an excellent acronym to remember this, it means "Producer Extends, Consumer Supers". This means that if you want your list to give you something, it's a producer, and you should use extends
. If you want your list to accept things from you, it's a consumer, so you use super
. See this answer for more.
但是如果我有一个没有边界的通配符呢?
<?>
限制您调用以泛型类型作为参数的方法和导致所有返回通用类型的方法返回 Object
。这是因为我们不知道什么类型是什么。例如,列表<?>
中的所有这些分配都是合法的:
It does both! <?>
restricts you from calling methods that take the generic type as an argument and causes all the methods that return the generic type to return Object
. This is because we have no idea what the type is whatsoever. For example, all of these assignments into a List<?>
are legal:
List<?> list;
list = new ArrayList<Integer>();
list = new ArrayList<String>();
list = new ArrayList<MyClass>();
等等。
这篇关于用于 '?延伸'和'?超级“在集合泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!