KTV和泛型(3)
泛型除了KTV,还有一个让人比较疑惑的玩意,而且它就是用来表达疑惑的:?
虽然通过泛型已经达到我们想要的效果了,例如:
List<String> list = new ArrayList<String>();
这样就可以放心地存取String类型的数据。
但是(抱歉,凡事总有个但是),应用的场景总是在不断增加的。某一天:
老板:咱们之前给客户开发的功能中有个地方要改一改。
神牛:哪里要改呢?
老板:以前你写的代码List<Cat> list = new ArrayList<Cat>();只能列出Java宠物店托管的猫咪,但是现在Java宠物店已经扩大了经营范围,希望列出他们保管所有的宠物,只要是宠物就行......
神牛:这个easy!
老板:真的吗?
于是,神牛一通操作,代码就改成了这样:
class Cat extends Pets {}; class Dog extends Pets {}; public static void main(String[] args) {
List<? extends Pets> list = new ArrayList<Pets>();
Pets pets = list.get(0);
Cat cat = (Cat)list.get(1);
Dog dog = (Dog)list.get(2);
}
然鹅,过了一段时间,Java宠物店由于经营不善,已经将之前的宠物转卖、送人了一部分,现在就剩一些猫科动物,所以现在的宠物笼子需要重新分配,只要是猫科动物就要往里放。以前写的代码
List<? extends Pets> list = new ArrayList<Pets>();
就满足不了给宠物分配笼子的需求了(先想一想为啥不行了?)
神牛继续把键盘一顿猛敲,代码又改成了这样:
class Felidae {};
class Cat extends Felidae {}; public static void main(String[] args) {
List<? super Felidae> list = new ArrayList<Felidae>();
Cat cat = new Cat();
list.add(cat);
}
这样一改,以前的功能又不能用了(为啥不能列出保管的宠物了?)
从以上需求场景可以看到:
1、对于不确定或者不关心实际要操作的类型,可以使用无界通配符(尖括号里一个问号,即 <?>),表示可以持有任何类型;
2、<? extends T>称之为「上界通配符」,表示只允许T及T的子类调用,例如只允许宠物类Pets的子类Cat和Dog调用;
3、<? super T>刚好相反,称之为「下界通配符」,表示只允许T及T的父类调用,例如只允许Cat的父类Felidae调用;
4、由于上界通配符<? extends T>中只知道T这个父类,而不知道具体的子类(所以用?代替),因此它无法实现向列表中加入新元素的功能,也就是做不到list.add()(这就是为什么满足不了给宠物分配笼子的需求);
5、而由于下界通配符<? super T>中只知道T这个子类,而不知道具体的父类(所以用?代替),因此它无法实现从列表中获取元素的功能,也就是做不到list.get()(这也是为什么满足不了列出保管的宠物)。
刚才说了那么多,稍稍有点绕。总结一下:
由于<? extends T>的只能取,不能存;而<? super T>得只能存,不能取,因此在架构设计中就有一个推荐的实践经验:
1、生产者producer一般用<? extends T>
2、消费者consumer一般用<? super T>
泛型讲到这里,如果能够全部明白,就可以真正畅快地去KTV嗨了。而泛型其他的知识点,像什么无界通配符、泛型参数一致性、多重限定、基类劫持接口、自限定类型、循环泛型等乱七八糟的可以统统不去管了,因为很多工程师一辈子的职业生涯中几乎都碰不到它们,除非点背到极点。还是最开始的那几个建议:
1、不钻牛角尖,有问题见招拆招
2、解决主要宏观上、业务上的问题,暂时忽略次要的技术上的、细节上的问题
3、抓大放小,用好80/20原则
最新文章
- mysql 表表连接的问题。
- thread.join 从异步执行变成同步
- HDU 5966 Guessing the Dice Roll
- thinkphp 数据访问
- java面试笔试
- Fast-cgi cgi nginx php-fpm 的关系 (转
- Android 开发环境搭建以及编译
- PHP图片上传程序(完整版)
- could only be replicated to 0 nodes, instead of 1
- SPSS方差分析
- Unity性能优化
- Flexbox布局指南
- 《全栈营销之如何制作个人博客》之二:php环境安装及个人博客后台搭建 让你的博客跑起来
- Android冷启动优化
- UBUNTU 16.04 安装AVD ";An error occurred while running ";android create avd
- Django+Xadmin打造在线教育系统(一)
- npm ERR! missing script: dev 报错解决
- 分享下使用 svn,测试服务器代码自动更新、线上服务器代码手动更新的配置经验
- Vue文件跳转$router传参数
- VC++实现程序重启的方法(转载)
热门文章
- B+树索引页大小是如何确定的?
- MyBatis ognl.NoSuchPropertyException 或者 Invalid bound statement (not found)
- 什么是云计算?云计算三种模式Sass、Paas、Iaas
- JWT签发与解析
- node前后端交互(Express)
- [CISCN2019 华北赛区 Day1 Web2]ikun-1|python反序列化
- Android Kotlin Annotation Processer
- Paperask一键获取A币
- Shell第四章《正则表达式》
- KingbaseES R6 集群repmgr.conf参数&#39;recovery&#39;测试案例(二)