Java逆变(Covariant)和协变(Contravariant)
1. 定义
逆变和协变描述的经过类型变换后的类型之间的关系。假如A
和B
表示类型,f
表示类型变换,A ≤B
表示A是B的子类型,那么
- 如果
A ≤B
,f(A) ≤f(B)
,那么f是协变 - 如果
A ≤B
,f(B) ≤f(A)
,那么f是逆变 - 如果两者都不是,那么f不变
这里的子类型并非是面向对象中继承关系中的子类型,它更多的是描述两个类型之间的兼容性。
2. 实例:泛型
考虑一个例子,假如f(A) = List<A>
,且List声明如下:
class List<T> { ... }
那么f是逆变,还是协变,又或者是不变?如果是协变意味着List<String>
是List<Object>
的子类型,如果是逆变意味着List<Object>
是List<String>
的子类型:
ArrayList<String> strings = new ArrayList<Object>(); // error
ArrayList<Object> objects = new ArrayList<String>(); // error
在Java中显然两者都不成立,所以说f是不变,且f表示泛型,即Java泛型是不变。
2. 实例:数组
再举个例子,假如f(A) = A[]
, 那么f是逆变,还是协变,又或者是不变?如果是协变意味着String[]
是Object[]
的子类型,如果是逆变意味着Object[]
是String[]
的子类型:
Object[] objects = new String[1];
可以看出,在Java中数组是协变。
Java逆变(Covariant)和协变(Contravariant)的更多相关文章
- Java 逆变与协变的名词说明
最近在研究Thinking in Java的时候,感觉逆变与协变有点绕,特意整理一下,方便后人.我参考于Java中的逆变与协变,但是该作者整理的稍微有点过于概念化,我在这里简单的说一下 我对于协变于逆 ...
- Java 逆变与协变
最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没 ...
- Java中的逆变与协变 很直接不饶弯的讲出来了
```java 协变 extends只能new 辈分比自己低的家伙 List<? extends Number> list001 = new ArrayList<Integer> ...
- Java泛型的协变与逆变
泛型擦除 Java的泛型本质上不是真正的泛型,而是利用了类型擦除(type erasure),比如下面的代码就会出现错误: 报的错误是:both methods have same erasure ...
- Java协变、逆变、类型擦除
协变.逆变 定义 Java中String类型是继承自Object的,姑且记做String ≦ Object,表示String是Object的子类型,String的对象可以赋给Object的对象.而Ob ...
- Scala中的协变,逆变,上界,下界等
Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...
- 协变(covariance),逆变(contravariance)与不变(invariance)
协变,逆变与不变 能在使用父类型的场景中改用子类型的被称为协变. 能在使用子类型的场景中改用父类型的被称为逆变. 不能做到以上两点的被称为不变. 以上的场景通常包括数组,继承和泛型. 协变逆变与泛型( ...
- C#中的协变OUT和逆变
泛型接口和泛型委托中经常使用可变性 in 逆变,out 协变 从 list<string>转到list<object> 称为协变 (string 从object 派生,那么 ...
- C# 逆变与协变
该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章<委托与匿名委托>.<匿名委托与Lambda表达式>以便帮你建立完整的知识体系 ...
随机推荐
- 页面嵌入iframe关于父子传参调用
1.首先来说一下iframe是干什么用的 IFRAME是HTML标签,作用是文档中的文档,或者浮动的框架(FRAME).iframe元素会创建包含另外一个文档的内联框架(即行内框架),通俗点说就是在一 ...
- spring Valid @Pattern 常见的验证表达式
1 匹配首尾空格的正则表达式:(^\s*)|(\s*$) 2 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$ 3 只能输入数字:"^[0-9]*$". 4 只 ...
- sitecore-多变量测试与A / B测试概念论述
sitecore-多变量检验和A / B检验的区别 A / B测试和多变量测试有什么区别?让我们来看看这些测试方法的方法,常见用途,优点和局限性. sitecore中A / B测试 A / B测试(您 ...
- Ubuntu Docker搭建GitLab以及常规配置使用
安装启动实例 1.首先创建一个目录用于存放配置 sudo docker pull docker.io/gitlab/gitlab-ce sudo mkdir -p /root/docker/gitla ...
- [转] Vue原理解析——自己写个Vue
一.Vue对比其他框架原理 Vue相对于React,Angular更加综合一点.AngularJS则使用了“脏值检测”. React则采用避免直接操作DOM的虚拟dom树.而Vue则采用的是 Obje ...
- java中的Date类
一.Date类简介 日期类主要包括Date类与Calendar类,这一节我们先介绍Date类, Date 表示特定的瞬间,精确到毫秒.Date类用于表示日期和时间,在计算机中的表示和我们现实世界使用差 ...
- 使用SqlConnectionStringBuilder构造数据库连接字符串
在实际开发过程中,很多时候会拷贝一个现有的数据库连接字符串,修改对应的数据库名.用户名.密码等配置成新的数据库连接字符串.但是有时候我们需要增加一些额外的配置,比如超时时间,最大连接池等,此时我们可以 ...
- Docker中上传镜像到docker hub中
原文参考:https://blog.csdn.net/sk_grace/article/details/81220675 申请Docker hub账号首先在https://hub.docker.com ...
- Java自学-接口与继承 多态
Java的多态 操作符的多态 +可以作为算数运算,也可以作为字符串连接 类的多态 父类引用指向子类对象 示例 1 : 操作符的多态 同一个操作符在不同情境下,具备不同的作用 如果+号两侧都是整型,那么 ...
- 使用DES算法实现加密解密
使用DES算法实现加密解密 我们常见的加密算法有DES.MD5.IDEA.AES等等,这篇随笔介绍使用DES算法实现加密解密 首先介绍一下DES算法: DES算法为密码体制中的对称密码体制,又被称为美 ...