Java泛型的协变和逆变
背景
文接上回,说到过Java的泛型擦除问题,这块我又联想到一个有意思的考点泛型的协变和逆变。
一、协变
首先Java的数组是协变的,所以假设A是B的父类,那么A[]是可以保存A或者B的对象的,并且A[]是B[]的父类。
<? extends T>
,写谁都会写,子类型限定。
相信大家也都见到过JDK中很多源码也有这么用,但为什么要这么写呢?
根因是Java的泛型没有协变类型,无法关联起来,也就没有关系。
利用通配符<? extends T>
,?代表子类,T为父类。
常见的例子比如,List<? extends Fruit> list = new ArrayList<Banana>();
实现向上转型,父类作为变量的申明,只能get(具体子类需强转),不能set。
二、逆变
<? super T>
,超类型限定。
逆变同样也是在各类源码中层出不穷,结合协变的理解,这块相信大家应该不难理解。
常见的例子比如,List<? super Apple> list = new ArrayList<Fruit>();
实现向下转型,子类作为变量的申明,只能set,不能get(只能放在Object对象)。
三、PECS
即Producer Extends,Consumer Super.
通俗理解生产者为协变,消费者为逆变。
针对于生产者,可取,有上界;针对于消费者,可存,有下界。
理解它,也可以通过Java的继承关系,
假设存在继承关系Object-》T、T-》A、T-》B
;
即T为A、B的父类,协变面向子类;逆变面向Object,它是所有对象的父类。
小结
1、协变、逆变的区别要分清
2、另外,再提一点泛型和通配符的区别,当然也可以结合第一点理解,
<T extends AAA>
用于定义泛型类和方法,擦除后为AAA类型;
<? extends AAA>
用于声明方法的形参,接收AAA和其子类型。
相关文章
- java 取余和取整_Java取整、取余
- java数组的声明_Java数组定义常用方法[通俗易懂]
- java 链表长度_Java实现单向链表[通俗易懂]
- java启动器_JAVA基础:Java 启动器如何查找类
- java CAS详解[通俗易懂]
- java运行机制是什么_JAVA运行机制
- java 中高级面试题_Java中高级面试题
- Java泛型深入理解「建议收藏」
- java平均的随机数_Java 随机数详解「建议收藏」
- java获取服务器路径_JAVA获取服务器路径的方法「建议收藏」
- JAVA中的泛型
- 【说站】java使用泛型的优势
- Java 8 的 java.util.function.* POJO 的反射新方法
- java 常量表达式,需要常量表达式? (Java switch语句)[通俗易懂]
- idea打开工程无法运行java程序_如何运行一个java程序
- 【JAVA冷知识】什么是逆变(contravariant)&协变(covariant)?数组支持协变&逆变吗?泛型呢?
- Java泛型的协变和逆变
- Java JDK1.5: 泛型 新特性的讲解说明
- 【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day08
- MongoDB for Java详解数据库
- java JNI: C 语言调用 Java 方法示例详解编程语言
- java实现Excel数据导出详解编程语言
- Java中的异常(Exception):什么是异常?异常产生的原因及常见的几种异常类型
- 使用Java操作MySQL数据库快速精准查询(java查询mysql数据库)
- 键Java使用Redis处理过期键(redisjava过期)
- 清除Java实现Redis过期Key的自动清理(redisjava过期)
- 机制解析Redis中Java过期机制(redisjava过期)
- 教程学习Java Redis:实战视频教程(javaredis视频)
- 使用Java轻松读取Redis数据 – 一步一步指南!(java读取redis)
- Linux系统中下载Java的方法(linux下java下载)
- Java如何在Linux下运行?(java执行linux)
- 如何在Linux系统中安装Java(linux中安装java)
- MySQL JDBC驱动Java与MySQL数据库的桥梁(mysql_jdbc驱动)
- Java中URL实现断点下载