首先来说:< ? extends T > 叫 上界通配符
< ? super T >叫 下界通配符
1. 下面用代码来说明上界通配符的一些特点
public class Fruit {
}
public class Apple extends Fruit {
}
public class Banana extends Fruit{
}
public class Plate<T> {
private T item;
public Plate(T item) {
super();
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
//下面为测试代码
Plate<? extends Fruit> plate = new Plate<Apple>(new Apple());
Object item3 = plate.getItem();
Fruit item = plate.getItem();
Apple item2 = plate.getItem();//error
plate.setItem(new Apple());//error
plate.setItem(new Banana());//error
1). plate< ? extends Fruit > 编译器只知道容器内是存放的Fruit或者它的子类,但是并不知道是apple还是banana,只能知道上限是Fruit。
所以Apple item2 = plate.getItem();//error
2).原因是编译器只知道容器内是Fruit或者它的派生类,但具体是什么类型不知道。可能是Fruit?可能是Apple?也可能是Banana,编译器在看到后面用Plate赋值以后,盘子里没有被标上有“苹果”。而是标上一个占位符:CAP#1,来表示捕获一个Fruit或Fruit的子类,具体是什么类不知道,代号CAP#1。然后无论是想往里插入Apple或者Banana或者Fruit编译器都不知道能不能和这个CAP#1匹配,所以就都不允许。
所以:plate.setItem(new Apple());//error
plate.setItem(new Banana());//error
2 说明下界通配符的特点
Plate<? super Fruit> plate2 = new Plate<Fruit>(new Fruit());
//取数据
Object object = plate2.getItem();
Fruit fruit = plate2.getItem();//error
//存数据
plate2.setItem(new Apple());
plate2.setItem(new Banana());
plate2.setItem(new Fruit());
因为下界规定了元素的最小粒度的下限,实际上是放松了容器元素的类型控制.元素的下界为Fruit,那么存数据的时候,可以存Fruit的子类。但是注意:取数据时只有Object才能装下,这样做会使数据类型的信息丢失。
3.PECS(product extends customer super)
经常取数据时 用<? extends T>上界通配符
经常存数据时 用<? super T>下界通配符