泛型通配符之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的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...
最新文章
- (转)动态SQL和PL/SQL的EXECUTE IMMEDIATE选项
- leetcode-581-Shortest Unsorted Continuous Subarray
- mysql 匹配所有记录_如何记录mysql中所有的查询
- 浅谈CSS3中的弹性布局
- 导致集群重启_园区网核心交换机S7706异常重启导致无线网络故障
- 全国计算机二级雷同卷怎么处理,信息系统项目管理师考试结束后,雷同卷怎么判定你知道吗?...
- 学习BIOS与CMOS区别
- Linux知识--初始linux
- 对数组名取地址a和 数组首地址a
- 柔性太阳能电池pdf_CIS太阳能电池.pdf
- Go测试远控免杀学习
- Centos 7系统密码破解
- Html5代码实现动态时钟
- 基于Java的奖学金评定管理系统
- 关闭msmpeng_你知道吗?把电脑系统里的这些进程关闭掉,可以提升系统流畅
- 测试小故事74:没有计划的日子
- latex 行内公式和行间公式高亮问题、多行高亮问题
- 前端进击的巨人(六):知否知否,须知this
- mimo节能模式smps_SMPS的完整形式是什么?
- 专线网络与家庭宽带区别(基础篇)