package com.rq.util.module.exercise.capture;
/**
* 频繁读取内容的使用 上界(extends)
* 频繁插入的,用下界(skuper)
* @author rq
*
*/
public class TestCapture2 {
@SuppressWarnings("unused")
public static void main(String[] args) {
Plate<Fruit> fruitPlate = new Plate<Fruit>(new Apple());
Fruit apple = new Apple(); // 元素之间的转型没有问题
// Plate<Fruit> applePlate = new Plate<Apple>(new Apple()); // Apple类型的plate, 无法转成 Fruit类型的plate,,容器之前不能转型
// 不能存、只能取
Plate<? extends Fruit> applePlate = new Plate<Apple>(new Apple()); // 允许Fruit及其子类的容器创建
Fruit a1 = applePlate.get(); // 1*** 本质是一个强制转换,?的类型一定是泛型的子类(或等于泛型本身),因此此处是一个向上转型,不用强制转换,类型安全** 但是调用方法只能是父类的,子类未重写的方法全部丢失 **
Object a2 = applePlate.get();
// Apple a3 = applePlate.get(); // 编译器只知道容器内饰Fruit或其派生类(子类),具体不知道,可能是Apple、Banana、GreenApple...
// applePlate.put(new Apple()); // 无论插入什么类型的值,编译器都不知道能不能和泛型匹配,所以都不允许插入 <capture#3-of ? extends Fruit> is not applicable for the arguments (Apple)
// <?> 表示任意内容,区分 <? extends ??>
applePlate.put(null);
Plate<? super Fruit> superFruitPlate1 = new Plate<Fruit>(new Apple()); // Fruit及其基类(父类)的容器创建
Plate<? super Fruit> superFruitPlate2 = new Plate<Food>(new Apple());
superFruitPlate1.put(new Fruit());
superFruitPlate1.put(new Apple());
// Apple a3 = superFruitPlate1.get(); // 既然元素是Fruit的基类,那么往里存的数据比Fruit小的都可以,但是取值就麻烦了,只有所有类的基类Object才能装
// Fruit a4 = superFruitPlate1.get();
Object a5 = superFruitPlate1.get(); // 2*** 本质依然是强制转化,不过此处?是泛型的父类(或泛型本身),父类转子类需要强制转换,类型不安全,可调用方法可从子类中找,父类中不一定有,会有异常
}
}
/**
* declare a container
* @author rq
*
* @param <T>
*/
class Plate<T>{
private T item;
public Plate(T t){
this.item = t;
}
public T get(){return this.item;}
public void put(T t){this.item = t;}
}
class Food{}
class Meat extends Food{}
class Fruit extends Food{}
class Apple extends Fruit{}
class Banana extends Fruit{}
class Pork extends Meat{}
class Beef extends Meat{}
class RedApple extends Apple{}
class GreenApple extends Apple{}package com.rq.util.module.exercise.capture;
/