今天在写代码的时候使用到了这样一个方法签名:

public void foo(Map<String, String> map);

在写这个参数的时候正好在想一些关于泛型的东西,于是:

public void foo(Map<? extends String, ? extends String> map);

这两种写法有什么区别呢?记得以前和同学讨论过这个问题,但后来没有记下来,渐渐又淡忘了。今天又去翻了好多资料,总算找到一些可以参考的,赶紧记在这里方便以后温故知新啦。好了,言归正传,上面这个问题主要涉及的是Java泛型中重要的PECS法则。那么PECS是什么呢?

我们知道Java泛型可以有多种写法,主要是 extendssuper 关键字。比如:

HashMap<T extends String>;
HashMap<? extends String>;
HashMap<T super String>;
HashMap<? super String>;

? extends

List<Apple> apples = new ArrayList<Apple>();
List<? extends Fruit> fruits = apples; //works, apple is a subclass of Fruit.
fruits.add(new Strawberry());        //compile error

fruits是一个Fruit的子类的List,由于Apple是Fruit的子类,因此将apples赋给fruits是合法的,但是编译器会阻止将Strawberry加入fruits。因为编译器只知道fruits是Fruit的某个子类的List,但并不知道究竟是哪个子类,为了类型安全,只好阻止向其中加入任何子类。那么可不可以加入Fruit呢?很遗憾,也不可以。事实上,不能够往一个使用了? extends的数据结构里写入任何的值。

但是,由于编译器知道它总是Fruit的子类型,因此我们总可以从中读取出Fruit对象:

Fruit fruit = fruits.get(0);

? super

List<Fruit> fruits = new ArrayList<Fruit>();
List<? super Apple> = fruits;
fruits.add(new Apple());                 //work
fruits.add(new RedApple());              //work
fruits.add(new Fruit());                 //compile error
fruits.add(new Object());                //compile error

这里的fruits是一个Apple的超类(父类,superclass)的List。同样地,出于对类型安全的考虑,我们可以加入Apple对象或者其任何子类(如RedApple)对象,但由于编译器并不知道List的内容究竟是Apple的哪个超类,因此不允许加入特定的任何超类型。

而当我们读取的时候,编译器在不知道是什么类型的情况下只能返回Object对象,因为Object是任何Java类的最终祖先类。

PECS原则总结

从上述两方面的分析,总结PECS原则如下:

如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)

如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)

如果既要存又要取,那么就不要使用任何通配符。

转载于:https://blog.51cto.com/flyingcat2013/1616068

Java泛型中的PECS原则相关推荐

  1. Java 泛型中的PECS原则

    在泛型编程时,使用部分限定的形参时,<? super T>和<? extends T>的使用场景容易混淆,PECS原则可以帮助我们很好记住它们: 生产者(Producer)使用 ...

  2. Java 泛型中的 PECS 原则

    PECS 即 producer extends, Consumer super 如果想要获取, 那么推荐使用 ? extends T 如果想要存放, 那么推荐使用 ? super T @Testpub ...

  3. pecs_Java泛型中的PECS原则

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

  4. java pecs_『Java』泛型中的PECS原则

    Java编程中有时我们要用到不确定的元素,通常用通配符"?"表示,其中" ? extends T "叫"上界通配符", " ? s ...

  5. Java泛型中extends和super的理解(转)

    E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...

  6. Java泛型中extends T和super T的区别?

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...

  7. Java泛型中extends和super的区别?

    区别 <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概 ...

  8. 聊一聊Java 泛型中的通配符 T,E,K,V,?

    点击上方"方志朋",选择"设为星标" 回复"1024"获取独家整理的学习资料 作者:glmapper juejin.im/post/5d57 ...

  9. 聊一聊-JAVA 泛型中的通配符 T,E,K,V,?

    前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据 ...

最新文章

  1. pthread_mutex_lock用法
  2. 10款免费工具:敏捷开发运维(DevOps)的好帮手
  3. 使用localStorage写一个简单的备忘录
  4. 星期三—用JAVA制作简易的通讯软件
  5. 双亲委派模型【理解】
  6. 类似与fiddler的抓包工具 burp suite free edition
  7. ESP8266(3)
  8. 西狐爱墙:为中国祈福!
  9. java7 diamond_java7新特性之Diamond syntax
  10. LoRa及LoRaWAN简介
  11. 计算机网络实验:CISCO IOS 路由器基本配置
  12. 网优5g前景_5G网络优化工程师的前景和待遇
  13. 大数据项目之电商数仓DataX、DataX简介、DataX支持的数据源、DataX架构原理、DataX部署
  14. 织梦配置多个mysql_织梦教程:DEDECMS中MYSQL修复表的两个小技巧
  15. 计算机当中的存储单位
  16. 现在我们家BB 28周了
  17. 【高级算法】模拟退火算法解决3SAT问题(C++实现)
  18. python实现视频格式转化、调节视频播放速度(仅需三行代码)
  19. 【操作系统】进程的三种基本状态及其转换
  20. 摸鱼神器:悄悄股票盯盘_stockAssistant 功能介绍

热门文章

  1. 孙正义真会玩,这个「人不是人,狗不是狗」的画面,价值上千万
  2. 移动版“全功能”Photoshop发布!还有AI剪视频一键传抖音、一键抠图功能上线 | Adobe MAX 2019...
  3. io分析神器blktrace
  4. 《C++语言入门经典》一2.8 左值与右值
  5. java----代理机制或动态类的生成
  6. VIM 命令使用大全
  7. Linux下使用Apache实现域名转发(Tomcat/JBOSS)
  8. JavaScript Table排序
  9. 分布式系统架构设计系列文章
  10. DPDK — DPDK APP 的指令行参数