<?超级T>和<?延伸T>在Java [英] Difference between <? super T> and <? extends T> in Java
问题描述
List< ;? super T>
和列表<?扩展T>
?
我以前使用 List<?扩展T>
,但它不允许我添加元素 list.add(e)
,而 List< ;?超级T>
允许。
我想知道差异。
extends
通配符 List < extends Number> foo3
表示这些都是法定作业:
列表< ;? extends Number> foo3 = new ArrayList< Number>(); // NumberextendsNumber(在这种情况下)
List< ;? extends Number> foo3 = new ArrayList< Integer>(); // Integer extends Number
List< ;? extends Number> foo3 = new ArrayList< Double>(); // Double extends Number
-
strong> - 鉴于上述可能的赋值,您确定要从
列表foo3
中读取的对象类型:
- 您可以读取
号
,因为任何可分配给foo3
包含数字
或数字
的子类。 li>您不能读取Integer
,因为foo3
可能指向List < <> c。 / code>可以指向
列表<整数>
。
- 您可以读取
-
写 - 考虑到上述可能的赋值,你可以在
List foo3
中添加什么类型的对象, > all 上面可能的ArrayList
赋值:
- t添加
Integer
,因为foo3
可能指向List< Double> $
- 您不能添加
Double
,因为foo3
- t添加
- 您不能添加
code>,因为
foo3
可能指向列表<整数>
。
您不能向列表< ;?添加任何对象扩展T>
,因为你不能保证它真的指向什么类型的 List
,所以你不能保证对象是允许的在列表
中。唯一的保证是你只能从它读取,你会得到一个 T
或子类 T
super
考虑列表< ;?
通配符声明<>超整数> foo3
表示这些都是法定作业:
列表< ;?超整数> foo3 = new ArrayList< Integer>(); // Integer是一个超类的Integer(在这个上下文中)
List< ;?超整数> foo3 = new ArrayList< Number>(); // Number是Integer的超类
List< ;?超整数> foo3 = new ArrayList< Object>(); // Object is an superclass Integer
-
阅读 - 鉴于上述可能的分配,当您从
列表foo3
:
$阅读时,您保证接收什么类型的对象b $ b- 您不能保证
Integer
,因为foo3
指向列表<数字>
或列表< Object>
。 - 您不能保证有
Number
,因为foo3
可能指向List< Object& 保证您将获得
对象
的实例 code> 或Object
的子类(但不知道是什么子类)。
- 您不能保证
-
写入 - 考虑到上面可能的赋值,你可以在
List foo3
all 上述可能的ArrayList
作业合法:
- 您可以添加
Integer
,因为在上面的列表中允许使用Integer
。 - 您可以添加
Integer
子类的实例,因为Integer $ c $ c>
- 您不能添加
Double
,因为foo3
可能指向ArrayList
。 - 您不能添加
Number
,因为foo3
可能指向ArrayList< Integer>
/ li>
- 您不能添加
Object
,因为foo3
可能指向ArrayList< Integer>
。
- 您可以添加
PECS
请记住::
$ b
-
生产者扩展 - 如果您需要
列表
产生T
值(您想从列表中读取T
s),您需要使用?扩展T
,例如列表< ;? extends Integer>
。 -
消费者超级 - 如果您需要
/ code>以消费
T
值(您要将T
写入列表)使用声明它? super T
,例如列表< ;? super Integer>
。但是不能保证您可以从此列表中读取什么类型的对象。 -
如果需要从列表中读取和写入,声明它完全没有通配符,例如
列表<整数>
示例
注意此示例来自Java泛型常见问题。请注意源列表 src
(生成列表)如何使用 extends
,目标列表 dest
(消费列表)使用 super
:
public class Collections {
public static< T> void copy(List< ;? super T> dest,List< ;? extends T> src)
{
for(int i = 0; i< src.size(); i ++)
dest .set(i,src.get(i));
}
}
另请参阅
如何添加到List< ;? extends Number>数据结构?
What is the difference between List<? super T>
and List<? extends T>
?
I used to use List<? extends T>
, but it does not allow me to add elements to it list.add(e)
, whereas the List<? super T>
allows.
I want to know the difference.
extends
The wildcard declaration of List<? extends Number> foo3
means that any of these are legal assignments:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
Reading - Given the above possible assignments, what type of object are you guarenteed to read from
List foo3
:- You can read a
Number
because any of the lists that could be assigned tofoo3
contain aNumber
or a subclass ofNumber
. - You can't read an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't read a
Double
becausefoo3
could be pointing at aList<Integer>
.
- You can read a
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can't add an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't add a
Double
becausefoo3
could be pointing at aList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aList<Integer>
.
- You can't add an
You can't add any object to List<? extends T>
because you can't guarantee what kind of List
it is really pointing to, so you can't guarantee that the object is allowed in that List
. The only "guarantee" is that you can only read from it and you'll get a T
or subclass of T
.
super
Now consider List <? super T >
.
The wildcard declaration of List<? super Integer> foo3
means that any of these are legal assignments:
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from
List foo3
:- You aren't guaranteed an
Integer
becausefoo3
could be pointing at aList<Number>
orList<Object>
. - You aren't guaranteed an
Number
becausefoo3
could be pointing at aList<Object>
. - The only guarantee is that you will get an instance of an
Object
or subclass ofObject
(but you don't know what subclass).
- You aren't guaranteed an
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can add an
Integer
because anInteger
is allowed in any of above lists. - You can add an instance of a subclass of
Integer
because an instance of a subclass ofInteger
is allowed in any of the above lists. - You can't add a
Double
becausefoo3
could be pointing at aArrayList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aArrayList<Integer>
. - You can't add a
Object
becausefoo3
could be pointing at aArrayList<Integer>
.
- You can add an
PECS
Remember PECS: "Producer Extends, Consumer Super".
"Producer Extends" - If you need a
List
to produceT
values (you want to readT
s from the list), you need to declare it with? extends T
, e.g.List<? extends Integer>
. But you cannot add to this list."Consumer Super" - If you need a
List
to consumeT
values (you want to writeT
s into the list), you need to declare it with? super T
, e.g.List<? super Integer>
. But there are no guarantees what type of object you may read from this list.If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g.
List<Integer>
.
Example
Note this example from the Java Generics FAQ. Note how the source list src
(the producing list) uses extends
, and the destination list dest
(the consuming list) uses super
:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src)
{
for (int i=0; i<src.size(); i++)
dest.set(i,src.get(i));
}
}
Also see How can I add to List<? extends Number> data structures?
这篇关于<?超级T>和<?延伸T>在Java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!