首页 > Java > 什么是PECS?和 有什么区别?ListList

什么是PECS?和 有什么区别?ListList

上一篇 下一篇

什么是PECS(生产者扩展消费者超级)?和 有什么区别?List<? super T>List<? extends T>

我曾经使用过,但它不允许我向它添加元素,而 确实如此。List<? extends T>list.add(e)List<? super T>

分割线

网友回答:

想象一下,拥有这种层次结构

enter image description here

1. 扩展

通过写作

    List<? extends C2> list;

您是说将能够引用类型(例如)的对象,其泛型类型是(包含)的 7 个子类型之一:listArrayListC2C2

  1. C2:、(可以存储 C2 或子类型的对象)或new ArrayList<C2>();
  2. D1:、(可以存储 D1 或子类型的对象)或new ArrayList<D1>();
  3. D2:、(可以存储 D2 或子类型的对象)或…new ArrayList<D2>();

等等。七种不同的情况:

    1) new ArrayList<C2>(): can store C2 D1 D2 E1 E2 E3 E4
    2) new ArrayList<D1>(): can store    D1    E1 E2  
    3) new ArrayList<D2>(): can store       D2       E3 E4
    4) new ArrayList<E1>(): can store          E1             
    5) new ArrayList<E2>(): can store             E2             
    6) new ArrayList<E3>(): can store                E3             
    7) new ArrayList<E4>(): can store                   E4             

对于每种可能的情况,我们都有一组“可存储”类型:此处以图形方式表示 7 个(红色)集

enter image description here

如您所见,并非每种情况都通用的安全类型

  • 你不能,因为它可能是list.add(new C2(){});list = new ArrayList<D1>();
  • 你不能,因为它可能是list.add(new D1(){});list = new ArrayList<D2>();

等等。

2. 超级

通过写作

    List<? super C2> list;

您是说将能够引用类型(例如)的对象,其泛型类型是(包括)的 7 个超类型之一:listArrayListC2C2

  • A1:、(可以存储 A1 或子类型的对象)或new ArrayList<A1>();
  • A2:、(可以存储 A2 或子类型的对象)或new ArrayList<A2>();
  • A3:、(可以存储 A3 或子类型的对象)或…new ArrayList<A3>();

等等。七种不同的情况:

    1) new ArrayList<A1>(): can store A1          B1 B2       C1 C2    D1 D2 E1 E2 E3 E4
    2) new ArrayList<A2>(): can store    A2          B2       C1 C2    D1 D2 E1 E2 E3 E4
    3) new ArrayList<A3>(): can store       A3          B3       C2 C3 D1 D2 E1 E2 E3 E4
    4) new ArrayList<A4>(): can store          A4       B3 B4    C2 C3 D1 D2 E1 E2 E3 E4
    5) new ArrayList<B2>(): can store                B2       C1 C2    D1 D2 E1 E2 E3 E4
    6) new ArrayList<B3>(): can store                   B3       C2 C3 D1 D2 E1 E2 E3 E4
    7) new ArrayList<C2>(): can store                            C2    D1 D2 E1 E2 E3 E4

对于每种可能的情况,我们都有一组“可存储”类型:此处以图形方式表示 7 个(红色)集

enter image description here

如您所见,这里我们有七种每种情况通用的安全类型:、。C2D1D2E1E2E3E4

  • 您可以,因为无论我们引用哪种列表,都是允许的list.add(new C2(){});C2
  • 您可以,因为无论我们引用哪种列表,都是允许的list.add(new D1(){});D1

等等。您可能注意到,这些类型对应于从类型开始的层次结构。C2

笔记

如果您想进行一些测试,这里是完整的层次结构

interface A1{}
interface A2{}
interface A3{}
interface A4{}

interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}

interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}

interface D1 extends C1,C2{}
interface D2 extends C2{}

interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}

分割线

网友回答:

extends

通配符声明意味着其中任何一个都是合法的赋值:List<? extends Number> foo3

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
  1. 读取 – 给定上述可能的分配,您可以保证从什么类型的对象中读取:List foo3
    • 您可以读取数字,因为可以指定为包含 .foo3NumberNumber
    • 您无法读取 ,因为可能指向 .Integerfoo3List<Double>
    • 您无法读取 ,因为可能指向 .Doublefoo3List<Integer>
  2. 写作 – 鉴于上述可能的赋值,对于上述所有可能的赋值,您可以添加哪种类型的对象是合法的:List foo3ArrayList
    • 您无法添加 ,因为可能指向 .Integerfoo3List<Double>
    • 您不能添加 ,因为可能指向 .Doublefoo3List<Integer>
    • 您不能添加 ,因为可能指向 .Numberfoo3List<Integer>

您不能将任何对象添加到 List<? extend T>,因为您无法保证它真正指向哪种 List,因此您无法保证该对象在该列表中是允许的。唯一的“保证”是你只能从中读取,你会得到一个T或T的子类。

super

现在考虑 .List <? super T>

通配符声明意味着其中任何一个都是合法的赋值:List<? super Integer> foo3

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
  1. 阅读 – 给定上述可能的分配,当您从以下位置阅读时,您保证会收到什么类型的对象:List foo3
    • 不能保证您是 ,因为可能指向 或 。Integerfoo3List<Number>List<Object>
    • 不能保证您是 ,因为可能指向 .Numberfoo3List<Object>
    • 唯一的保证是你会得到一个对象或子类的实例(但你不知道是什么子类)。Object
  2. 写作 – 鉴于上述可能的赋值,对于上述所有可能的赋值,您可以添加哪种类型的对象是合法的:List foo3ArrayList
    • 您可以添加 ,因为上述任何列表中都允许 an。IntegerInteger
    • 您可以添加子类的实例,因为上述任何列表中都允许子类的实例。IntegerInteger
    • 您无法添加 ,因为可能指向 .Doublefoo3ArrayList<Integer>
    • 您无法添加 ,因为可能指向 .Numberfoo3ArrayList<Integer>
    • 您无法添加 ,因为可能指向 .Objectfoo3ArrayList<Integer>

胸 肌

记住PECS:“生产者延伸,消费者超级”。

  • “生产者扩展” – 如果您需要 a 来生成值(您想从列表中读取 s),您需要用 声明它,例如 。但您无法添加到此列表中。ListTT? extends TList<? extends Integer>
  • “Consumer Super” – 如果你需要 a 来消费值(你想将 s 写入列表中),你需要用 来声明它,例如 。但是不能保证您可以从此列表中读取哪种类型的对象。ListTT? super TList<? super Integer>
  • 如果你需要同时读取和写入列表,你需要完全声明它,没有通配符,例如。List<Integer>

请注意 Java 泛型常见问题解答中的此示例。请注意源列表(生产列表)如何使用 ,目标列表(消费列表)如何使用:srcextendsdestsuper

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

另请参阅
如何添加到列表<?扩展数字>数据结构?

分割线

网友回答:

我喜欢@Bert F的答案,但这是我的大脑看待它的方式。

我手里拿着一个X。如果我想将我的 X 写入一个列表,该列表必须是 X 的列表或我的 X 可以在我编写它们时被放大到的事物列表,即 X 的任何超类……

List<? super   X>

如果我得到一个列表,并且我想从该列表中读取一个 X,那最好是 X 列表或一个在我读出它们时可以向上转换为 X 的事物列表,即任何扩展 X 的东西

List<? extends X>

模板简介:该模板名称为【什么是PECS?和 有什么区别?ListList】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Java】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 223次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 03-13
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
企业网站 响应式 单页式简历模板 微信文章 微信模板 微信素材 微信图片 html5 微信公众平台 自适应
您可能会喜欢的其他模板