之前在讀《Java編程思想》中的泛型一章時(shí),對于
? super MyClass
為什么叫超類型通配符一直不理解哭靖,既然可以往List<? super Apple>
中添加Apple
的子類,那?
代表的不應(yīng)該是子元素嗎欺冀,如果代表的是子元素树绩,那? extends MyClass
和? super MyClass
有啥區(qū)別啊。今天終于從牛角尖里鉆出來了隐轩,感覺自己之前好蠢饺饭,理解能力太差,哈哈哈哈...
public class GenericTest {
public static void main(String[] args) {
List<? super Apple> list1 = new ArrayList<Fruit>();
List<? super Apple> list2 = new ArrayList<Apple>();
// 這樣會報(bào)錯(cuò)职车,因?yàn)?代表的是Apple的父類
List<? super Apple> list3 = new ArrayList<RedApple>();
list2.add(new RedApple());
// 這樣會報(bào)錯(cuò)瘫俊,因?yàn)閘ist2中的元素為Apple
list2.add(new Fruit());
Object obj = list1.get(0);
// 這樣會報(bào)錯(cuò)
Fruit fruit = list1.get(0);
// 這樣也會報(bào)錯(cuò)
Apple apple = list1.get(0);
// 這樣還會報(bào)錯(cuò)
RedApple redApple = list1.get(0);
}
private static class Fruit {}
private static class Apple extends Fruit {}
private static class RedApple extends Apple {}
}
其實(shí)List<? super Apple>
的含義是指現(xiàn)有的這個(gè)容器中的元素要么是Apple
,要么是Apple
的父類悴灵】秆浚可以看到給List<? super Apple>
賦值為ArrayList<Apple>()
和ArrayList<Fruit>()
是沒問題的,但是賦值為ArrayList<RedApple>()
就會報(bào)錯(cuò)积瞒,因?yàn)?code>RedApple是Apple
的子類川尖,不符合List<? super Apple>
的聲明。這樣稱super
為超類型通配符也就說的通了茫孔,而且Apple
位于繼承樹的最底下叮喳,所以也可以稱super
為下界通配符。
既然List<? super Apple>
中的元素是Apple
或Apple
的父類缰贝,那么向List<? super Apple>
中添加RedApple
也是合法的馍悟,因?yàn)?code>RedApple也是Apple
啊,但是添加Fruit
是不行的剩晴,因?yàn)?code>List<? super Apple>中存放的元素可能為Apple
锣咒。當(dāng)從List<? super Apple>
中獲取元素時(shí),只能獲取到Object
類型李破,因?yàn)榧偃?code>Apple為接口類型的話宠哄,那么元素的父類就不確定了,但所有的類都繼承自Object
嗤攻,Object
是確定的毛嫉。所以父類型通配符一般用于向一個(gè)泛型類型中“寫入”(傳遞給一個(gè)方法)。
public class GenericTest {
public static void main(String[] args) {
List<? extends Fruit> list1 = new ArrayList<Fruit>();
List<? extends Fruit> list2 = new ArrayList<Apple>();
// 這樣會報(bào)錯(cuò)妇菱,因?yàn)?代表的是Fruit的子類
List<? extends Fruit> list3 = new ArrayList<Plant>();
// 這里0索引是沒有值的哈承粤,主要是說明下extends的特性
Fruit fruit = list2.get(0);
// 這樣會報(bào)錯(cuò)
list2.add(new Orange());
}
private static class Plant {}
private static class Fruit extends Plant {}
private static class Apple extends Fruit {}
private static class Orange extends Fruit {}
}
與super
相反暴区,List<? extends Fruit>
的含義是指現(xiàn)有的這個(gè)容器中的元素要么是Fruit
,要么是Fruit
的子類辛臊,所以稱extends
為子類型通配符仙粱,因?yàn)槿萜髦械乃性囟祭^承自Fruit
,所以Fruit
是所有元素的上界彻舰,也就可以稱extends
為上界通配符伐割。
既然List<? extends Fruit>
中的元素都是Fruit
的子類,那么從List<? extends Fruit>
中獲取類型為Fruit
的元素自然也是合法的刃唤。但是向List<? extends Fruit>
中添加元素是不允許的隔心,可以看到雖然list2
的引用類型為List<? extends Fruit>
,看上去好像可以向其中添加Orange
對象尚胞,但list2
實(shí)際上是ArrayList<Apple>
類型的列表硬霍,里面的元素都是Apple
,而Orange
和Apple
是沒有關(guān)系的笼裳。所以子類型通配符一般用于從一個(gè)泛型類型中“讀取”(從一個(gè)方法中返回)唯卖。