Java 泛型 PECS

在stackoverflow上看到兩篇關(guān)于java泛型 PECS 的問答:

  1. Difference between <?super T> and <?extends T> in java
  2. How can I add to List <?extends Number> data structures

PECS

Remember PECS:"Producer Extends,Consumer Super"

  • "Producer Extends" - If you need a <code>List</code> to produce <code>T</code> values (you want to read <code>T</code>s from the list), you need to declare it with <code>? extends T</code>, e.g. <code>List<? extends Integer></code>. But you cannot add to this list.

  • "Consumer Super" - If you need a <code>List</code> to consume <code>T</code> values (you want to write <code>T</code>s into the list), you need to declare it with <code>? super T</code>, e.g. <code>List<? super Integer></code>. But there are no guarantees what type of object you may read from this list.

  • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. <code>List<Integer></code>.

也就是說:

  • 當(dāng)你僅僅需要從<code>List</code>中讀出<code>T</code>,那么你需要使用<code>? extends T</code>.例如<code>List<? extends Integer></code>
  • 當(dāng)你僅僅需要將T寫入<code>List</code>時匀钧,那么你需要使用<code>? super T</code>.例如<code>List<? super Integer></code>
  • 當(dāng)你既需要讀也需要寫時,你應(yīng)該直接使用T. <code>List< Integer></code>

PECS的使用

extends

<code>List<? extends Number> foo</code> 表示<code>foo</code>可以存儲一族的類型的值(而不是一個特殊的類型的值)耕突,所以下面的聲明都是正確的:

List<? extends Number> foo = new ArrayList<Number>;  // Number "extends" Number
List<? extends Number> foo = new ArrayList<Integer>; // Integer extends Number
List<? extends Number> foo = new ArrayList<Double>;  // Double extends Number

正因為<code>foo</code>表示存儲的是一族的類型的值,無法保證具體指向的類型蔬浙,所以我們無法保證我們<code>add</code>的對象是<code>List</code>允許的類型逗栽。假如我們<code>add</code>一個<code>Integer</code>的值,但是<code>foo</code>可能指向<code>Double</code>(第三條語句)怠晴,我們<code>add</code>一個<code>Double</code>的值,<code>foo</code>可能指向<code>Integer</code>(第二條語句)浴捆。

雖然無法<code>add</code>蒜田,但是我們可以保證我們從<code>foo</code>中取出來的值肯定是屬于<code>Number</code>或者是<code>Number</code>的子類,所以我們可以從<code>foo</code>中獲取值选泻。

super

關(guān)于<code>List<? super T></code>冲粤,以下聲明是正確的:

List<? super Number> foo = new ArrayList<Number>; // Number is a "super" of Number
List<? super Number> foo = new ArrayList<Object>; // Object is a "super" of Number

因為<code>foo</code>的類型無法確定,可能是<code>Number</code>页眯,也可能是<code>Number</code>的父類梯捕,我們無法保證讀出來的值的類型,所以無法從<code>List</code>中讀出值窝撵。但是我們可以保證我們插進去的值肯定屬于<code>Number</code>或者<code>Number</code>的父類傀顾,因此我們可以使用<code>add</code>。

JDK中的例子

<code>Collections.copy()</code>的方法簽名:

public static <T> void copy(List<? super T> dest,List<? extends T> src)

在<code>src</code>中碌奉,我們可以傳入與<code>T</code>類型相關(guān)的<code>List</code>短曾,并且能夠保證取出的是<code>T</code>類型或者<code>T</code>的子類型的值。

在<code>dest</code>中赐劣,我們可以傳入<code>T</code>類型和<code>T</code>的父類的<code>List</code>嫉拐,并且能夠保證我們從存放的值都滿足要求。

例如:

// copy(dest, src)
Collections.copy(new ArrayList<Number>(), new ArrayList<Number());
Collections.copy(new ArrayList<Number>(), new ArrayList<Integer());
Collections.copy(new ArrayList<Object>(), new ArrayList<Number>());
Collections.copy(new ArrayList<Object>(), new ArrayList<Double());

有興趣的同學(xué)可以去看原文魁兼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婉徘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咐汞,更是在濱河造成了極大的恐慌盖呼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碉考,死亡現(xiàn)場離奇詭異,居然都是意外死亡挺身,警方通過查閱死者的電腦和手機侯谁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人墙贱,你說我怎么就攤上這事热芹。” “怎么了惨撇?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵伊脓,是天一觀的道長。 經(jīng)常有香客問我魁衙,道長报腔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任剖淀,我火速辦了婚禮纯蛾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纵隔。我一直安慰自己翻诉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布捌刮。 她就那樣靜靜地躺著碰煌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绅作。 梳的紋絲不亂的頭發(fā)上芦圾,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音棚蓄,去河邊找鬼堕扶。 笑死,一個胖子當(dāng)著我的面吹牛梭依,可吹牛的內(nèi)容都是我干的稍算。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼役拴,長吁一口氣:“原來是場噩夢啊……” “哼糊探!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起河闰,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤科平,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后姜性,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞪慧,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年部念,在試婚紗的時候發(fā)現(xiàn)自己被綠了弃酌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氨菇。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妓湘,靈堂內(nèi)的尸體忽然破棺而出查蓉,到底是詐尸還是另有隱情,我是刑警寧澤榜贴,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布豌研,位于F島的核電站,受9級特大地震影響唬党,放射性物質(zhì)發(fā)生泄漏鹃共。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一初嘹、第九天 我趴在偏房一處隱蔽的房頂上張望及汉。 院中可真熱鬧,春花似錦屯烦、人聲如沸坷随。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽温眉。三九已至,卻和暖如春翁狐,著一層夾襖步出監(jiān)牢的瞬間类溢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工露懒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闯冷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓懈词,卻偏偏與公主長得像蛇耀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坎弯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理纺涤,服務(wù)發(fā)現(xiàn),斷路器抠忘,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • 對象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法撩炊,而不是構(gòu)造函數(shù)創(chuàng)建對象:僅僅是創(chuàng)建對象的方法,并非Fa...
    孫小磊閱讀 1,963評論 0 3
  • ? extend 這次崎脉,代碼就編譯不過去了拧咳!Java編譯器會阻止你往一個Fruit list里加入strawber...
    今晚打肉山閱讀 1,071評論 0 1
  • 參考 & 推薦 Effective Java(2nd Edition)December, 2017 馬上就要出版第...
    xiaofudeng閱讀 8,798評論 1 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法囚灼,內(nèi)部類的語法骆膝,繼承相關(guān)的語法砾淌,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399