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 Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
阅读 - 鉴于上述可能的分配,您保证从 List foo3
读取什么类型的对象:
您可以阅读 Number
因为任何可以分配给 foo3
的列表包含 Number
或 Number
的子类.
您无法阅读 Integer
因为 foo3
可能指向 List<Double>
.
你看不懂 Double
因为 foo3
可能指向 List<Integer>
.
写作 - 鉴于上述可能的分配,您可以将什么类型的对象添加到 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 Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
阅读 - 鉴于上述可能的分配,当您从 List foo3
读取时,您保证收到什么类型的对象:
您不能保证获得 Integer
因为 foo3
可能指向 List<Number>
或 List<Object>
.
您不能保证获得 Number
因为 foo3
可能指向 List<Object>
.
只有保证你会得到一个 的实例Object
或 Object
的子类(但你不知道子类是什么)。
写作 - 鉴于上述可能的分配,您可以将什么类型的对象添加到 List foo3
这对 来说是合法的全部 以上可能 ArrayList
作业:
您可以添加 Integer
因为一个 Integer
允许在上述任何列表中。
您可以添加 Integer
的子类的实例因为 Integer
的子类的实例允许在上述任何列表中。
您不能添加 Double
因为 foo3
可能指向 ArrayList<Integer>
.
您不能添加 Number
因为 foo3
可能指向 ArrayList<Integer>
.
您不能添加 Object
因为 foo3
可能指向 ArrayList<Integer>
.
职业教育学院
记住 PECS:
《生产者延伸,消费者超》 .
《生产者扩展》 - 如果您需要 List
生产T
值(你想从列表中读取 T
s),你需要用 ? extends T
声明它,例如List<? extends Integer>
.但是您不能添加到此列表中。
“消费 super ” - 如果您需要 List
消费 T
值(您想将 T
写入列表中),您需要使用 ? super T
声明它,例如List<? super Integer>
.但是不能保证您可以从此列表中读取什么类型的对象。
如果您需要读取和写入列表,则需要完全声明它,没有通配符,例如List<Integer>
.
例子
备注
this example from the Java Generics FAQ .注意源列表如何
src
(生产 list )使用
extends
,以及目的地列表
dest
(消费 list )使用
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));
}
}
另见
How can I add to List<? extends Number> data structures?
我是一名优秀的程序员,十分优秀!