文档章节

java协变、逆变

obaniu
 obaniu
发布于 08/20 16:47
字数 531
阅读 27
收藏 0

概念

假设

  • A、B表示类型
  • ≤ 表示继承关系
  • f<⋅>表示类型转换

若A ≤ B,则 A是B的子类,B是A的超类

协变、逆变

什么是型变?型变(type variance)允许对类型进行子类型转换。

为了下面讲解先定义几个类:

static class Animal {}
static class Human extends Animal {}
static class Wolf extends Animal {}
static class Man extends Human {}

1. 协变(covariant)

当A≤ B有 f<A> ≤f <B>

List<? extends Animal> list=new ArrayList<Human>();

子类通配符(也叫上界通配符)<? extends T>

规定了元素的根类是Animal,可get出Animal类型

Animal animal=list.get(0);

但不能add,继承自Animal的类型可以是Human也可以Wolf,若添加Wolf肯定出错所以编译器禁止

list.add(new Human());
list.add(new Wolf());

java中的数组默认支持协变的

Animal []array=new Animal[3];
array[0]=new Human();
array[1]=new Wolf();
array[2]=new Man();

2. 逆变(contravariant)

当A≤B有 f<B>≤f<A>

List<? super Human> list=new ArrayList<Animal>();

超类通配符(也叫下界通配符)<? super T>

规定了元素的超类是Human,所以可以add Human类型及其子类型

list.add(new Human());
list.add(new Man());

不可以 get Human类型,因为没明确指定统一的“根”(除Object),只能get出Object类型

Human h=list.get(0);

3. 不变(invariant)

当A≤B时上述协变、逆变均不成立

List<Object> list=new ArrayList<String>();

Java的泛型默认是不变的(在不使用上界/下界通配符的情况下)

生产者协变,消费者逆变

哪么实际使用中何时协变何时逆变呢?《Effective Java》总结好了:producer-extends, consumer-super(PECS)

  • 读取(get)的对象称为生产者(Producer),可从生产者中安全地读取;
  • 写入(add)的对象称为消费者(Consumer) ,可对消费者写入该类型和字类型(Human和Human的子类Man)。

© 著作权归作者所有

共有 人打赏支持
obaniu
粉丝 35
博文 76
码字总数 28863
作品 0
广州
高级程序员
Kotlin语言中的泛型设计哲学

Kotlin语言的泛型设计很有意思,但并不容易看懂。关于这个部分的官方文档,我反复看了好几次,终于弄明白Kotlin语言泛型设计的背后哲学。这篇文章将讲述Kotlin泛型设计的整个思考过程及其背后...

欧阳锋
04/16
0
0
Java泛型的协变、逆变和不变

背景 平时在看一些开源框架源码时总发现他们会或多或少的用到泛型来定义数据类型。这可以理解,毕竟牛逼的开源框架大都是为了解决一类普遍问题而存在的;但看不懂的是,有时参数或者返回值会...

JarryWell
07/11
0
0
Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh
06/11
0
0
Scala的协变(+),逆变(-),上界(:)

Scala的协变(+),逆变(-),上界(<:),下界(>:) 协变covariant、逆变contravariant、不可变invariant 对于一个带类型参数的类型,比如 List[T],如果对A及其子类型B,满足 List[B]也符合List[...

秋风醉了
2015/08/02
0
0
《Kotlin 极简教程 》第6章 泛型

第6章 泛型 《Kotlin极简教程》正式上架: 点击这里 > 去京东商城购买阅读 点击这里 > 去天猫商城购买阅读 非常感谢您亲爱的读者,大家请多支持!!!有任何问题,欢迎随时与我交流~ 6.1 泛型...

程序员诗人
2017/06/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用rancher界面化管理docker并部署springCloud项目的其中一个服务

一、先来个简单的 1.安装docker 2.安装eureka——运行docker命令安装 3.安装eureka——运行dokcer镜像安装 (1)构建eureka的镜像,网易云的docker镜像比较全一些,也可以去https://hub.docke...

monroeCode
22分钟前
2
0
理论与实践:如何从Hadoop迁移到MaxCompute

摘要:MaxCompute大数据计算服务,能提供快速、完全托管的PB级数据仓库解决方案,能够使用户经济且高效地分析处理海量数据。而用户往往之前使用了Hadoop实现大数据计算任务,在选择了阿里云大...

阿里云云栖社区
23分钟前
1
0
mysql: utf8 && utf8mb4

https://mathiasbynens.be/notes/mysql-utf8mb4 临时收藏

阿dai
34分钟前
1
0
面试宝典系列-nginx限流

Nginx自身有的请求限制模块ngx_http_limit_req_module、流量限制模块ngx_stream_limit_conn_module基于令牌桶算法,可以方便的控制令牌速率,自定义调节限流,实现基本的限流控制。 如何Ngi...

suyain
35分钟前
2
0
下拉框选择数据过滤?

需求:下拉框数据新增一条数据,已选择的不能再重新被选择 数据:存放表格数据的数组 scoreTable 下拉框数据 catorgaryArr 定义一个已经选择了的id数组 catorgaryIds 实现: arr 使用来保存每...

西园里的猫
40分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部