<之间的区别?超级T>和<?扩展 Java 中的 T>1. 扩展2. 超级笔记
和 有什么区别?List<? super T>
List<? extends T>
我曾经使用过,但它不允许我添加元素,而它却允许。List<? extends T>
list.add(e)
List<? super T>
和 有什么区别?List<? super T>
List<? extends T>
我曾经使用过,但它不允许我添加元素,而它却允许。List<? extends T>
list.add(e)
List<? super T>
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
数字
,因为可以指定的任何列表都包含 的一个或一个子类。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 添加任何对象<? 扩展 T>
因为您无法保证它真正指向哪种类型的 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
写作 - 鉴于上述可能的赋值,您可以添加哪种类型的对象对于上述所有可能的赋值都是合法的:List foo3
ArrayList
Integer
Integer
Integer
Integer
Double
foo3
ArrayList<Integer>
Number
foo3
ArrayList<Integer>
Object
foo3
ArrayList<Integer>
请记住PECS:“生产者延伸,消费者超级”。
“Producer Extends” - 如果您需要 a 来生成值(您想从列表中读取 s),则需要使用 声明它,例如 .但您无法添加到此列表中。List
T
T
? extends T
List<? extends Integer>
“Consumer Super” - 如果你需要一个来消费的值(你想把s写进列表),你需要用 来声明它,例如。但是不能保证您可以从此列表中读取哪种类型的对象。List
T
T
? super T
List<? super Integer>
如果您需要同时读取和写入列表,则需要在没有通配符的情况下完全声明它,例如.List<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 C2> list;
您是说将能够引用类型(例如)的对象,其泛型类型是( include)的7个子类型之一:list
ArrayList
C2
C2
new ArrayList<C2>();
new ArrayList<D1>();
new ArrayList<D2>();
等等。七种不同的情况:
1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
2) new ArrayList<D1>(): can store D1 E1 E2
3) new ArrayList<D2>(): can store D2 E3 E4
4) new ArrayList<E1>(): can store E1
5) new ArrayList<E2>(): can store E2
6) new ArrayList<E3>(): can store E3
7) new ArrayList<E4>(): can store E4
对于每种可能的情况,我们都有一组“可存储”类型:此处以图形方式表示 7 个(红色)集
如您所见,并非每种情况都通用的安全类型:
list.add(new C2(){});
list = new ArrayList<D1>();
list.add(new D1(){});
list = new ArrayList<D2>();
等等。
通过写作
List<? super C2> list;
您是说将能够引用类型(例如)的对象,其泛型类型是( include)的7种超类型之一:list
ArrayList
C2
C2
new ArrayList<A1>();
new ArrayList<A2>();
new ArrayList<A3>();
等等。七种不同的情况:
1) new ArrayList<A1>(): can store A1 B1 B2 C1 C2 D1 D2 E1 E2 E3 E4
2) new ArrayList<A2>(): can store A2 B2 C1 C2 D1 D2 E1 E2 E3 E4
3) new ArrayList<A3>(): can store A3 B3 C2 C3 D1 D2 E1 E2 E3 E4
4) new ArrayList<A4>(): can store A4 B3 B4 C2 C3 D1 D2 E1 E2 E3 E4
5) new ArrayList<B2>(): can store B2 C1 C2 D1 D2 E1 E2 E3 E4
6) new ArrayList<B3>(): can store B3 C2 C3 D1 D2 E1 E2 E3 E4
7) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
对于每种可能的情况,我们都有一组“可存储”类型:此处以图形方式表示 7 个(红色)集
如您所见,这里我们有七种安全类型,它们在每种情况下都是通用的:,,,,,,。C2
D1
D2
E1
E2
E3
E4
list.add(new C2(){});
C2
list.add(new D1(){});
D1
等等。您可能注意到,这些类型对应于从类型 开始的层次结构。C2
这里的完整层次结构,如果你想做一些测试
interface A1{}
interface A2{}
interface A3{}
interface A4{}
interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}
interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}
interface D1 extends C1,C2{}
interface D2 extends C2{}
interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}