前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java泛型的协变和逆变

Java泛型的协变和逆变

原创
作者头像
Mark Sun
发布2023-02-27 23:11:45
6561
发布2023-02-27 23:11:45
举报
文章被收录于专栏: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和其子类型。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、协变
  • 二、逆变
  • 三、PECS
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档