PECS 是 “Producer Extends Consumer Super” 的缩写,是 Java 泛型中的重要用法。

PECS 就是当你需要遍历某一个类型和子类的集合数据时,集合相当于生产者,此时泛型使用 <? extends T>。当需要往某个类型的集合添加类和子类实例时,集合相当于消费者,此时泛型使用 <? super T>

每年八九月份的瓜是最甜的。

PECS

对 Java 泛型 PECS 的讲解中,大多是从参数使用的角度来的,本文结合调用传值和参数使用对比来看 PECS 的两种情况。

PE

当我们想要遍历读取某个集合时,需要使用 <? extends T>,用上面类型为例,为了方便查看编译时的错误,直接上截图:

当使用<? extends Watermelon>,类型的上限是 Watermelon,从集合取出的值默认就是 Watermelon,因此也能用父类定义去引用,所以方法前三个赋值正确,KylinWatermelon 错误。此时的集合除了可以 add(null) 外,不能添加任何其他类型,为什么不能添加?

我们从调用方看看:

调用方中,方法的参数不能是 ObjectFruit 的集合,可以是 Watermelons 和子类 KylinWatermelon,当这俩作为参数传递进去时,不能往 List<Watermelon> 中添加 Object, Fruit,不能往 List<KylinWatermelon>中添加 Object, Fruit,Watermelon。由于参数的类型不确定,因此除了null,其他都不能 add

CS

当需要往某个类型的集合添加类和子类实例时,集合相当于消费者,此时泛型使用 <? super T>

当使用<? super Watermelon>,类型的下限是 Watermelon。为了方便理解编译错误的原因,先看如何调用的方法:

调用时,参数必须是 Watermelon 或者父类型,当传递 objects, fruits, watermelons 时,从集合获取的类型是未知的,因此只能使用 Object 接收。当往集合添加值时,如果是 List<Watermelon> 就不能添加 Object, Fruit 类型,是 List<Fruit> 就不能添加 Object 类型,因此满足所有情况下的类型就只能是 Watermelon 和子类。

PECS虽然很早就知道,也看过很多遍,但是记不牢,每次从单方面理解时,总是很绕,但是结合调用和使用两方面时,一切都合情合理,理解很简单。

源码

public class PECSLearn {public static class Fruit {}public static class Watermelon extends Fruit {}public static class KylinWatermelon extends Watermelon {}public static void main(String[] args) {List<Object> objects = Arrays.asList(new Object());List<Fruit> fruits = Arrays.asList(new Fruit());List<Watermelon> watermelons = Arrays.asList(new Watermelon());List<KylinWatermelon> kylinWatermelons = Arrays.asList(new KylinWatermelon());producer(objects);//编译错误producer(fruits);//编译错误producer(watermelons);producer(kylinWatermelons);consumer(objects);consumer(fruits);consumer(watermelons);consumer(kylinWatermelons);//编译错误}public static void producer(List<? extends Watermelon> watermelons) {Object object = watermelons.get(0);Fruit fruit = watermelons.get(0);Watermelon watermelon = watermelons.get(0);KylinWatermelon kylinWatermelon = watermelons.get(0);//编译错误watermelons.add(null);watermelons.add(new Object());//编译错误watermelons.add(new Fruit());//编译错误watermelons.add(new Watermelon());//编译错误watermelons.add(new KylinWatermelon());//编译错误}public static void consumer(List<? super Watermelon> watermelons) {Object object = watermelons.get(0);Fruit fruit = watermelons.get(0);//编译错误Watermelon watermelon = watermelons.get(0);//编译错误KylinWatermelon kylinWatermelon = watermelons.get(0);//编译错误watermelons.add(new Object());//编译错误watermelons.add(new Fruit());//编译错误watermelons.add(new Watermelon());watermelons.add(new KylinWatermelon());}
}

Java 泛型的读写规则:PECS相关推荐

  1. Java泛型中的PECS原则

    今天在写代码的时候使用到了这样一个方法签名: public void foo(Map<String, String> map); 在写这个参数的时候正好在想一些关于泛型的东西,于是: pu ...

  2. java 泛型 t_Kotlin(2) 泛型与集合

    前言 以一个java老鸟的角度,如何去看 kotlin.Java源代码应该如何用Kotlin重构.如何正确学习kotlin并且应用到实际开发中.本文将会探究. 本文分两大块,重难点和潜规则. 重难点: ...

  3. Java泛型之PECS原则

    转载自: [Java]泛型中 extends 和 super 的区别? Java泛型详解 文章目录 通配符 上下界通配符的副作用 上界<? extends T>不能往里存,只能往外取 下界 ...

  4. java 泛型 PECS准则

      我们知道<?>表示:我想使用Java泛型来编写代码,而不是用原生类型:但是在当前这种情况下,我并不能确定下泛型参数的具体类型,因此用?表示任何某种类型.因此,根据我们对通配符的了解,使 ...

  5. 一篇文章教你学会Java泛型

    文章目录 一.原生态类型 1.什么是原生态类型 2.使用原生态类型 有什么不好 3.泛型的子类型规则 4.泛型的可擦除性 二.泛型常用形式 1.泛型方法 2.泛型单例工厂 三.有限制的通配符类型 四. ...

  6. java泛型视频教程_Java泛型快速教程

    java泛型视频教程 泛型是Java SE 5.0引入的一种Java功能,在其发布几年后,我发誓那里的每个Java程序员不仅会听说过,而且已经使用过. 关于Java泛型,有很多免费和商业资源,而我使用 ...

  7. 一文通关苦涩难懂的Java泛型

    前言 相信大家对Java泛型并不陌生,无论是开源框架还是JDK源码都能看到它,毫不夸张的说,泛型是通用设计上必不可少的元素,所以真正理解与正确使用泛型,是一门必修课,本文将解开大家对泛型的疑惑,并通过 ...

  8. 深入理解 Java 泛型

    首先提个问题: Java 泛型的作用是什么?泛型擦除是什么?泛型一般用在什么场景? 如果这个问题你答不上来,那这篇文章可能就对你有些价值. 读完本文你将了解到: 什么是泛型 为什么引入泛型 泛型的使用 ...

  9. 3万字死磕Java泛型所有细节知识点,看这一篇就够了

    1 泛型 1.0 前言--为什么要死磕Java泛型 不知道阅读这篇文章的你是否曾跟我一样,在没有阅读<Java核心技术>前查阅了大量的Java泛型文章,但是在实际使用泛型的过程中,总是觉得 ...

最新文章

  1. 【AI参赛经验】汉字书法识别比赛经验心得——by:microfat_htu
  2. 动态规划(DP)通俗讲解
  3. pandas库scatter_matrix绘图可视化参数详解
  4. poj 1469 COURSES
  5. 图像隐藏matlab代码,picture Matlab简单操作实现图像的隐藏加密 联合开发网 - pudn.com...
  6. Tomcat 配置 项目 到tomcat目录外面 和 域名绑定访问(api接口、前端网站、后台管理网站)...
  7. 前端一HTML:八:css中与文本相关的属性
  8. 容器与Pod到底有什么区别和联系?
  9. 在Brackets中使用jsHint遇到的问题
  10. linux刻录win10u盘_手把手教你装系统之【制作官方win10安装U盘】
  11. r语言worldclim数据_R语言空间数据分析(五):栅格数据处理
  12. power bi可视化表_在Power BI报表视图中创建可视化
  13. android服务常驻后台,android-如何始终在后台运行服务?
  14. hdu 1333水题
  15. .NET 漫淡(一) --- 需要充分认识的应用程序域-AppDomain
  16. scratch3.0入门
  17. 配置HP LaserJet M1536dnf MFP打印机通过TCPIP共享多台计算机
  18. HDFS--Secondary NameNode
  19. 163邮箱登陆写信自动化脚本
  20. OneZero第四次站立会议(2016.3.24)

热门文章

  1. wincc上位机与1200组态步骤_博途v13的wincc能组态上位机吗
  2. redis关闭保护模式
  3. 低耦合高内聚什么意思?
  4. ora-01722 无效数字
  5. 使用SQL Server数据库支持SharePoint的5条技巧
  6. h5页面的雷达图 五边形_konva canvas插件写雷达图示例
  7. C语言——aabb问题
  8. qnx 镜像文件_一种基于Hypervisor的QNX操作系统启动方法及装置与流程
  9. lua table源码学习
  10. Python csv reader 跳过第一行表头