泛型通配符之PECS
目录
基础知识点
上限通配符
List中上限通配符的add()方法
List中上限通配符的get()方法
下限通配符
List中下限通配符的add()方法
List中下限通配符的get()方法
基础知识点
开始先了解一下基础知识点:
在Java中,向上转型是允许的,但向下转型会无法编译通过。如果强转,有可能会抛出ClassCastException异常。那么如果真要向下转型,平时我们要一般都会先用instanceof来判断是否是这个类型,如果是,才进行强转。
废话不多说,上代码:
class A {
}class B extends A {
}class C extends B {
}
上限通配符
上限通配符:? extends B ,表示某类型的父类是B(或者说,某类型继承于B),它和类的extend是一样的。
List中上限通配符的add()方法
它负责放入一个某种类型的对象到List中。在下面这个代码块代码中,这个某种类型肯定是B的子类类型。
List<? extends B> extendList = new ArrayList<>();
extendList.add(new Object());//编译报错
extendList.add(new A());//编译报错
extendList.add(new B());//编译报错
extendList.add(new C());//编译报错
extendList.add(null); //可以放入,因为null不是有效的对象实例。
为什么除了add(null),其它的都不能通过编译呢?
因为编译器只知道extendList应该放入B的子类,但并不知道放B的哪个子类。也就是说如果B有1万个子类,某种类型就有1万种类型的可能,这个时候没办法判断它具体是那个类型。由于编译器不懂是B的哪个子类,在执行add方法时,无法进行类型转换成某个指定的类放入List,所以只能放入null,而不能放入其它的对象。
有人可能会说为啥Object也不行?因为Object是所有类的父类,但是由于向下转型正常也是编译不通过的,所以也不能放入。
List中上限通配符的get()方法
它负责从某种类型的List方法中返回某种类型的值。在下面这个代码块中,这个某种类型是B的子类型,加上在java中向上转型是允许的,所以可以返回类型为B及其父类型的值(例如:A类型,以及所有类的父类Object)。但是编译器依旧不能确定是B类型的哪个子类,所以就算B类型只有一个子类C,也不能直接返回C类型的对象(除非强转)。
注:它就是PECS中的PE,即produce -> extend ,下面代码中表示List是生产者,你只能从这个List里面往外面拿(给别人)。
List<? extends B> extendList = new ArrayList<>();
B b = extendList.get(0);//正常
A a = extendList.get(0);//正常向上转型
C c = extendList.get(0);//编译报错
下限通配符
下限通配符:? super B ,表示某类型是B的父类型,和代码中调用父类方法的super关键字类似。
List中下限通配符的add()方法
它负责放入一个某种类型的对象到List中。在下面这个代码块代码中,这个某种类型肯定是B的父类类型。
注:它就是PECS中的CS,即consumer -> super ,下面代码中表示这个List集合是消费者,你只能往里面放(给它消费)。
List<? super B> superList = new ArrayList<>();
superList.add(new Object());//编译报错
superList.add(new A());//编译报错
//某种类型肯定是B的父类型,所以只能放入B或B的子类,才能向上转型
superList.add(new B());
superList.add(new C());
superList.add(null); //可以放入,因为null不是有效的对象实例。
为什么这个List<? super B>可以执行add方法呢?
虽然编译器可以知道B的所有父类,但是它也没法知道这个某种类型具体是B的哪一个父类类型,所以你可以放入B及B的子类型(向上转型)。
List中下限通配符的get()方法
因为编译器不懂返回的是什么类型,只知道是B类型的父类,所以只能返回一个Object(因为它是所有类的父类)。
Object object = superList.get(0);//正常
A a1 = superList.get(0);//编译报错
B b1 = superList.get(0);//编译报错
C c1 = superList.get(0);//编译报错
泛型通配符之PECS相关推荐
- 学员优秀博文赏析:泛型通配符及约束
最课程师徒班的同学正在红红火火的学习中.仿佛.应该.必须,到了跟大家阶段性汇报成果的时候了.为什么,因为毕竟当时把师徒班说的那么好,就业班的同学该要闹革命了. 师徒班相较于就业班,虽然课程内容和总量完 ...
- java pecs_『Java』泛型中的PECS原则
Java编程中有时我们要用到不确定的元素,通常用通配符"?"表示,其中" ? extends T "叫"上界通配符", " ? s ...
- 泛型(派生子类,泛型通配符,类型擦除)
目录 从泛型类派生子类 1.子类不是泛型类,明确父类类型 2.子类和父类都是泛型类 泛型通配符 1.类型通配符上限 2.类型通配符下限 类型擦除 从泛型类派生子类 1.子类不是泛型类,明确父类类型 c ...
- [转]JAVA泛型通配符T,E,K,V区别,T以及ClassT,Class?的区别
原文地址:https://www.jianshu.com/p/95f349258afb 1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被 ...
- 不正确 有三种形式 说法 通配泛型_一看就懂 详解JAVA泛型通配符T,E,K,V区别...
1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...
- 【Java 泛型】泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )
文章目录 一.泛型类用法 二.泛型方法用法 三.泛型通配符 <?> 四.泛型安全检查 五.完整代码示例 1.泛型类 / 方法 2.main 函数 一.泛型类用法 泛型类用法 : 使用时先声 ...
- java 文件通配符_Java中泛型通配符的使用方法示例
本文实例讲述了Java中泛型通配符的使用方法.分享给大家供大家参考,具体如下: 一 点睛 引入通配符可以在泛型实例化时更加灵活地控制,也可以在方法中控制方法的参数. 语法如下: 泛型类名 extend ...
- java学习(134):泛型通配符的使用
import java.util.ArrayList; import java.util.List;//泛型通配符的使用 public class test73 {public static void ...
- java for(o t :object) 获取顺序号_JAVA泛型通配符T,E,K,V区别 瞬间豁然开朗
1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...
最新文章
- python3.6.4安装教程-python3.6.4如何安装到树莓派3代
- wp7技术类网站汇总
- C++(2)--代码结构
- nodejs 创建一个静态资源服务器 +路由
- MySQL主从失败:slave_IO_Running为No
- JVM内存分析及导致内存溢出的不健壮代码及解决办法
- linux内核模块的程序结构
- PHP留言并展示_留言页面展示功能
- SQL Azure 服务器端架构
- Python全栈学习_day010作业
- oracle必须配置哪个参数,oracle – 此操作必须将ORA-02069 global_names参数设置为TRUE...
- 高斯误差函数erf的数值计算方法(C++实现)
- PDF怎么编辑,如何给PDF添加书签
- 系统重装后恢复MySQL数据
- 单片机c语言程序编写步骤,Proteus运行Keil编写的51单片机C语言步骤
- 服务器虚拟机双活,VMware双活数据心解决方案详解.pptx
- 【可视化开发】数据大屏可视化技术汇总
- Dijkstra算法指定任意两点距离(邻接矩阵法)
- android 自定义 对号,Android 自定义View 对勾CheckBox
- 编写windbg调试器扩展 入门篇1