泛型中 的區別


?T 是什么?

? 是通配符,T 是類型變量。根據字面意思,<? extends T> 表示 任何繼承自類型 T 的類型<? super T> 表示 任何是類型 T 的超類的類型

上界和下界

泛型的關系-extends.png

下面代碼就是 上界通配符(Upper Bounds Wildcards)
Plate<? extends Fruit> 

它的表意是,一個能放 Fruit 及其子類的盤子。


泛型的關系-super.jpg

下面代碼就是 下界通配符(Lower Bounds Wildcards)
Plate<? super Fruit> 

它的表意是,一個能放 Fruit 及其父類的盤子。

PECS 原則

1. <? extends T> 不能往里存,只能往外取

class Plate<T> { private T item; public Plate(T t) { item = t; } public void set(T t) { item = t; } public T get() { return item; } } 

往里存的意思就是,不能對泛型 T 類型所代表的成員變量 item 進行賦值(賦值成一種特定類型)。往外取的意思就是對泛型 T 類型所代表的成員變量 'item' 進行進行類型轉換(轉換成一種特定類型)。

Plate<? extends Fruit> p = new Plate<Apple>(new Apple()); // 不能被存入任何元素 p.set(new Fruit()); // exception p.set(new Apple()); // exception // 取出來的東西只能放在 Fruit 或它的基類里 Fruit fruit = p.get(); Object object = p.get(); Apple apple = p.get(); 
  • 注意以上代碼,只有在構造函數中可以對 T 類型的 item 進行賦值,通過 set 方法進行賦值是不行的。原因是編譯器通過 <? extends Fruit> 只知道 Plate 接受的是 Fruit 及其子類,但是具體是哪個不能確定。但是從寫法上,我們在構造時已經顯式地指明了 Plate 的類型是 Apple,為什么編譯器還不知道呢?這是因為 JVM 在設計初期就沒有考慮過泛型,因此對於 JVM 編譯成的字節碼來說,也沒有泛型的概念,JVM 會使用一個占位符 CAP#1 來表示 Plate 接受一個 Fruit 或子類。所以無論想往 Plate 插入任何類型都不可以(因為你不能賦值一個 CAP#1 類型)
  • 但是,將 <? extends Fruit> 替換為一個具體的類型,set 方法就是生效的。這是因為編譯器已經知道 Plate 只會接受一個確定類型的水果 Apple
Plate<Apple> applePlate = new Plate<>(new Apple()); applePlate.set(new Apple()); Apple apple = applePlate.get(); applePlate.set(new GreenApple()); 
  • 但是下面的寫法是不被接受的。因為泛型 T 是一個類型變量,它不能被用於表達式中。
Plate<T extends Fruit> p = new Plate<>(new Apple()); 
  • 如果寫 Plate<?>,則表示 Plate 中放的是任意類型,因此什么也存不進去,可以往外取 Object
Plate<?> anyPlate = new Plate<>(new Apple()); Object o = anyPlate.get(); 

其實存不進去的根本原因是因為,Java 類沒有一個共同的子類,但是卻有一個共同的父類 Object。所以永遠可以向上轉型取數據,卻不能向下轉型存數據。

2. 下界 <? super Fruit> 不影響往里存,但是往外取只能放在 Object

使用下界 <? super Fruit> 的意思是,Plate 中存放的是任意 Fruit 的基類,但是不確定是哪一個。因此往里放 Fruit 以及其子類一定是可以的(因為這些類一定是 <? super Fruit> 的子類)。但是往外取時就只能是 Object,因為編譯器不知道你存的是 Fruit 還是 MeatFruitMeat 就只有一個共同父類,那就是 Object。因此往外取 Object 一定是對的。

3. PECS(Producer Extends Consumer Super)

3.1 Producer Extends 你寫的類是主要作為生產者向外提供數據,那么就用 extends
3.2 Consumer Super 你寫的類是主要作為消費者,需要吃進數據,那么就用 super


作者:你可記得叫安可
鏈接:https://www.jianshu.com/p/0808c0029b2d
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM