extends
通配符声明
List<? extends Number> foo3意味着以下任何一项都是合法转让:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends NumberList<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
Reading -根据上述可能的任务,可以保证从中读取哪种类型的对象List foo3:
你可以阅读
“ a”
,Number因为任何可以分配为foo3
包含Number
或的子类的列表Number。- 你看不到,
Integer
因为它foo3
可能指向List<Double>
。 你看不到
a,Double
因为它foo3
可能指向List<Integer>
。Writing -鉴于上述可能的分配,你可以添加哪种类型的对象对上述所有可能的分配List foo3都是合法的:ArrayList
你不能添加,Integer因为它foo3可能指向
List<Double>
。- 你不能添加,Double因为它foo3可能指向
List<Integer>
。 - 你不能添加,Number因为它foo3可能指向
List<Integer>
。
你不能向其中添加任何对象,
List<? extends T>因为你无法保证List它真正指向的是哪种对象,因此你不能保证该对象中允许使用该对象List。唯一的“保证”是,你只能从中读取内容,并且会获得的T或子类 T。
super
现在考虑
List <? super T>。
通配符声明
List<? super Integer> foo3意味着以下任何一项都是合法转让:
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 IntegerList<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
Reading -鉴于上述可能的任务,当你从中阅读时,可以保证接收什么类型的对象List foo3:
你不能保证一个Integer因为foo3可能指向List
或List - 你不能保证一定会Number因为foo3可能指向List
该唯一的保证是,你会得到一个实例Object或子类的Object(但你不知道什么是子类)。
Writing -鉴于上述可能的分配,你可以添加哪种类型的对象对上述所有可能的分配List foo3都是合法的:ArrayList
你可以添加,
Integer
因为Integer
上述任何列表中都允许使用。- 你可以添加的子类
Integer
的实例,因为Integer
上述任何列表中都允许的的子类的实例。 - 你不能添加,
Double
因为它foo3
可能指向ArrayList<Integer>
。 - 你不能添加,
Number
因为它foo3
可能指向ArrayList<Integer>
。 - 你不能添加,
Object
因为它foo3
可能指向ArrayList<Integer>
。
PECS
记住PECS:“生产者扩展,消费者超级”。
“Producer Extends” -如果需要a List来产生T值(T要从列表中读取s),则需要使用进行声明?
extends T,例如
List<? extends Integer>。但是你不能添加到此列表。
“Consumer Super” -如果需要
a List来使用T值(要将Ts写入列表中),则需要使用进行声明?
super T,例如
List<? super Integer>。但是不能保证你可以从该列表中读取什么类型的对象。
- 如果你既要读取列表又要写入列表,则需要完全声明它而没有通配符,例如
List<Integer>
。
例
注意Java Generics FAQ中的这个例子。请注意源列表
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)); } }


