溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java泛型的PE和CS原則說明

發(fā)布時間:2021-09-04 11:48:46 來源:億速云 閱讀:181 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“Java泛型的PE和CS原則說明”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java泛型的PE和CS原則說明”吧!

什么是 PE,CS

PE,CS全稱是producer extends,consumer super的縮寫,這是 Joshua Bloch 在 Effective Java 一書 中引入的一個略顯奇怪的術(shù)語,但有助于理解泛型的用法。換言之,參數(shù)化類型代表 生產(chǎn)者(producer)則使用 extends, 代表消費(fèi)者(consumer)則使用 super

PE 原則

簡單來說, PE 表示,如果你的方法只是想從集合獲取值,并且希望集合的類型范圍是T及其子類,那么泛型可以定義為 ? extends T

了解泛型的同學(xué)應(yīng)該知道 extends 是上界通配符,使用了上界通配符,只能讀取值,不能寫入值,取值的的類型是T

只能取值不能寫入的就是生產(chǎn)者,有人可能有點(diǎn)理解了,我們來個更詳細(xì)的解釋,舉個栗子

假設(shè),我們有個水果的對象,水果類有個addAll方法,用來將另一個水果集合,放入到水果對象內(nèi)

class Fruit{
    private List<Fruit> fruits = new LinkedList<>();

    public void addAll(List<Fruit> fruits){
        for (Fruit fruit : fruits) {
            this.fruits.add(fruit);
        }
    }
}

現(xiàn)在,我們需求變了,有蘋果,香蕉分別繼承了水果這個類,如果我么將蘋果或者香蕉集合直接放入addAll方法,會編譯報錯,因為蘋果集合,不是水果集合

public static void main(String[] args){
        List<Apple> appleList = new LinkedList<>();
        Fruit fruit = new Fruit();
        // 編譯報錯
        fruit.addAll(appleList);
}

class Apple extends Fruit{
}
class Banana extends Fruit{
}

如果我們要放進(jìn)去怎么辦,使用上界通配符,修改addAll方法,使用了上界通配符后,元素只能讀,不能寫,傳入的集合類型范圍是Fruit或者其子類集合

public void addAll(List<? extends Fruit> f){
    for (Fruit fruit : f) {
        this.fruits.add(fruit);
    }

有人會問了,這個上界通配符,跟PE有什么關(guān)系? 當(dāng)然有,PEproducer extends的縮寫,我們仔細(xì)看看,對于addAll方法來說,只是要消費(fèi)入?yún)?那么入?yún)⒕褪?strong>生產(chǎn)者,說著這,估計很多人已經(jīng)明白了

PE是針對方法來說的,如果某個方法的入?yún)?需要一個生產(chǎn)者,并且范圍是泛型的子類,那么使用上界通配符extends

CS 原則

簡單來說, CS 表示,如果你的方法只是想往集合寫入值,并且集合的類型范圍希望是T及其父類,那么泛型可以定義為 ? super T 來表示

了解泛型的同學(xué)應(yīng)該知道,super表示下界通配符,使用了下界通配符,只能寫入值,不能取值,寫入的值必須是T或者其子類

只能寫入,不能取出就是消費(fèi)者,有人可能有點(diǎn)理解了,我們來個更詳細(xì)的解釋,舉個例子

我們還是沿用上面的例子,我們進(jìn)行改造一下,蘋果類有個addAll方法,傳入一個蘋果集合,將蘋果對象放入這個集合里面

public class Apple extends Fruit{

    private Apple apple = new Apple();

    public void addAll(List<Apple> apples){
        apples.add(apple);
    }
}

現(xiàn)在需求變了,我們變更,我們想傳入一個更大的水果集合,將蘋果添加入水果集合里面,畢竟蘋果是屬于水果的子類,我們直接將水果集合傳入進(jìn)去,會編譯報錯,我們改造一下addAll方法,使用下界通配符將它的接收范圍擴(kuò)大,傳入的集合范圍是Apple或者其父類集合

public void addAll(List<? super Apple> apples){
    apples.add(apple);
}

有人會問了,這個下界通配符,跟CS有什么關(guān)系? 當(dāng)然有,CSconsumer super的縮寫,對于addAll方法來說,只要是將東西放進(jìn)到入?yún)?nèi),那么入?yún)⒕褪?strong>消費(fèi)者

CS也是針對方法來說的,如果某個方法的入?yún)⑿枰M(fèi)方法內(nèi)的東西,入?yún)⒉⑶沂欠盒偷母割?那么使用下界通配符super

總結(jié)

如果進(jìn)行簡單的歸納,那就是

  • 只從方法入?yún)⒓汐@取值,那么使用 extends

  • 只從方法入?yún)⒓蠈懭胫?那么使用 super

感謝各位的閱讀,以上就是“Java泛型的PE和CS原則說明”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java泛型的PE和CS原則說明這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI