廢話不多說,先上代碼,大家可以貼在單元測試中看下以方便理解
public class ExampleUnitTest {
class Food{}
class Fruit extends Food{}
class Meat 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{}
class Plate<T> {
private T item;
public Plate(T t){
this.item = t;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
@Test
public void test(){
//下面這句編譯報錯可以這樣理解Apple is a Fruit,but Apple's Plate is not Fruit's Plate
// Plate<Fruit> plate = new Plate<Apple>(new Apple()); //Error,編譯報錯
//上界通配符,Plate能裝所有的Fruit及Fruit的子類
Plate<? extends Fruit> plate1 = new Plate<>(new Apple());
// plate1.setItem(new Apple()); //Error 編譯器不通過 無法賦值
// plate1.setItem(new Fruit()); //Error 無法賦值
//為什么即使已經(jīng)指定了Apple類型卻還是會報錯,是因?yàn)榫幾g器只知道容器內(nèi)是Fruit或者它的子類
//上界只能從盤中取出,取出來的東西只能放在Fruit以及Fruit的基類中
Fruit item1 = plate1.getItem();//正確或有效用法
Object object = plate1.getItem();
// Apple item = plate1.getItem(); //Error 類型不匹配
//下界通配符規(guī)定了元素最小粒度的下限,既然元素是Fruit以及Fruit類型的基類,
// 那么往里存的粒度只要比Fruit類型小的都可以
Plate<? super Fruit> plate3 = new Plate<>(new Fruit());
Plate<? super Fruit> plate4 = new Plate<>(new Food());
Object item = plate3.getItem();//如果接收只能用Object類型,但取這個值毫無意義
//實(shí)際定義super下界通配符是為了set()賦值,但必須保證是Fruit以及Fruit的子類型才能編譯通過
plate3.setItem(new Fruit());
plate3.setItem(new Apple());
plate3.setItem(new RedApple());
// plate3.setItem(new Food());//Error
// plate4.setItem(new Food());//Error
plate4.setItem(new Apple());
plate4.setItem(new GreenApple());
}
}
總之一句話,頻繁往外讀取內(nèi)容用上界Extends,經(jīng)常往里寫入的適合用下界Super