Java 泛型 PECS

在stackoverflow上看到两篇关于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>.

也就是说:

  • 当你仅仅需要从<code>List</code>中读出<code>T</code>,那么你需要使用<code>? extends T</code>.例如<code>List<? extends Integer></code>
  • 当你仅仅需要将T写入<code>List</code>时,那么你需要使用<code>? super T</code>.例如<code>List<? super Integer></code>
  • 当你既需要读也需要写时,你应该直接使用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

关于<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>类型相关的<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());

有兴趣的同学可以去看原文。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,561评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,218评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,162评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,470评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,550评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,806评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,951评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,712评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,166评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,510评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,643评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,306评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,930评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,745评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,983评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,351评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,509评论 2 348

推荐阅读更多精彩内容