文档章节

泛型协变、逆变

obaniu
 obaniu
发布于 2018/08/20 16:47
字数 592
阅读 44
收藏 0

无论是java、C#、kotlin还是scala,都会遇到泛型中的协变、逆变场景,算是泛型必学技。本文的概念、思想在其他三门语言也是通用的,学会包您一招通杀。

概念

假设

  • 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
粉丝 37
博文 83
码字总数 39241
作品 0
广州
高级程序员
私信 提问
谈谈.Net中的协变和逆变

谈谈.Net中的协变和逆变 关于协变和逆变要从面向对象继承说起。继承关系是指子类和父类之间的关系;子类从父类继承所以子类的实例也就是父类的实例。比如说Animal是父类,Dog是从Animal继承的...

长平狐
2012/06/08
87
0
c#中关于协变性和逆变性(又叫抗变)详解

  今天回忆了之前看的《深入理解C#》这本书中的泛型章节,其中对泛型的可变性的理解。泛型可变性分两种:协变和逆变。逆变也又称为抗变。  怎么理解这两个名词的意思:   ①:协变即为在...

奥斯卡的肌肤
2018/08/20
0
0
协变和逆变(转载)

前言 个人感觉协变(Covariance)与逆变(Contravariance)是 C# 4 中最难理解的一个特性了,因为 C# 4 用了一个非常直观的语法(和关键字),在很多情况下,这似乎很简单,用于输入的参数,用于...

jeffcky
2015/08/15
0
0
C# 4.0新特性-"协变"与"逆变"以及背后的编程思想

在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相...

长平狐
2012/09/04
390
0
一句话清晰总结协变和逆变

看到过园子里面几篇协变和逆变的文章,但是总觉得写得不够清晰,文章这东西注重要是要把自己想表达的观点表达出来,这个过程应该是把复杂的东西消化出来从而简单化,清晰化,而不是故弄玄虚,...

长平狐
2012/06/08
45
0

没有更多内容

加载失败,请刷新页面

加载更多

更换本地git仓库的远程地址

参考学习链接:https://blog.csdn.net/mlq8087/article/details/81360025 本地 Git 仓库根目录下:cd .git ; 编辑 Git 配置文件:vim config ; shift + i 进入input 编辑模式 ; 修改 [rem...

Liens
8分钟前
0
0
Install hadoop, install hive, 及hive的使用

hadoop , hive 安装过程和配置文件(附件)。 注意: hadoop Name Node未做ha. Hive, 还是基本的hive on MR, 未使用on tez, on spark, 未配置LLAP、 HCatalog and WebHCat。 安装完之后,以...

墨子Zhai
9分钟前
0
0
如何处理缓存失效、缓存穿透、缓存并发等问题

缓存失效:   引起这个原因的主要因素是高并发下,我们一般设定一个缓存的过期时间时,可能有一些会设置5分钟啊,10分钟这些;并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过...

我心中有猛狗
12分钟前
1
0
对于java 参数是值传递还是引用传递的

代码: package com.qimh.anotation;public class Test { static class Person{ private String name; public String getName() { return name;......

qimh
19分钟前
0
0
Pages Manager——可本地管理Pages服务内容,一键生成漂亮的文档界面。

Pages Manager Git地址 可本地管理Pages服务内容,一键生成漂亮的文档界面。在线预览 简单、轻便,无需安装数据库。 框架:spring-boot 数据库:sqlite 原理 本地维护一组markdown文档 将mar...

tanghc
29分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部