1. 定义

逆变和协变描述的经过类型变换后的类型之间的关系。假如AB表示类型,f表示类型变换,A ≤B表示A是B的子类型,那么

  • 如果A ≤Bf(A) ≤f(B),那么f是协变
  • 如果A ≤Bf(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)的更多相关文章

  1. Java 逆变与协变的名词说明

    最近在研究Thinking in Java的时候,感觉逆变与协变有点绕,特意整理一下,方便后人.我参考于Java中的逆变与协变,但是该作者整理的稍微有点过于概念化,我在这里简单的说一下 我对于协变于逆 ...

  2. Java 逆变与协变

    最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没 ...

  3. Java中的逆变与协变 很直接不饶弯的讲出来了

    ```java 协变 extends只能new 辈分比自己低的家伙 List<? extends Number> list001 = new ArrayList<Integer> ...

  4. Java泛型的协变与逆变

    泛型擦除 Java的泛型本质上不是真正的泛型,而是利用了类型擦除(type erasure),比如下面的代码就会出现错误: 报的错误是:both methods  have same erasure ...

  5. Java协变、逆变、类型擦除

    协变.逆变 定义 Java中String类型是继承自Object的,姑且记做String ≦ Object,表示String是Object的子类型,String的对象可以赋给Object的对象.而Ob ...

  6. Scala中的协变,逆变,上界,下界等

    Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...

  7. 协变(covariance),逆变(contravariance)与不变(invariance)

    协变,逆变与不变 能在使用父类型的场景中改用子类型的被称为协变. 能在使用子类型的场景中改用父类型的被称为逆变. 不能做到以上两点的被称为不变. 以上的场景通常包括数组,继承和泛型. 协变逆变与泛型( ...

  8. C#中的协变OUT和逆变

    泛型接口和泛型委托中经常使用可变性 in  逆变,out  协变 从 list<string>转到list<object> 称为协变 (string 从object 派生,那么 ...

  9. C# 逆变与协变

    该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章<委托与匿名委托>.<匿名委托与Lambda表达式>以便帮你建立完整的知识体系 ...

随机推荐

  1. KB,MB,GB,TB,PB,EB,ZB,YB,BB

    1 Bit = Binary Digit 8 Bits = 1 Byte 1024 Bytes = 1 Kilobyte 1024 Kilobytes = 1 Megabyte 1024 Megaby ...

  2. 设置KAFKA

    让我们继续下载并设置Kafka,启动zookeeper,集群,生产者和消费者.   要下载Kafka,请参阅此链接  http://kafka.apache.org/downloads.html 下载 ...

  3. Linux命令注释—HDFS运维

    HDFS运维—命令注释 1 实验背景 HDFS是大数据其他组件的基础,Hive的数据存储在HDFS中,Mapreduce.Spark 等计算数据也存储在HDFS 中,HBase 的 region 也是 ...

  4. Github Markdown 图片如何并排显示

    Github Markdown 图片如何并排显示   要一张图片接着一张图片的写,中间不能有换行.如果换行的话则图片也换行 正确的写法: ![描述](图片链接)![描述](图片链接)![描述](图片链 ...

  5. jwt的简单使用

    目录 简介 java版本 golang版本 简介 使用jwt对数据进行存储加密,分为java和golang版本. java版本 maven配置 <dependency> <group ...

  6. java基本数据类型的变量

    一.整型变量 短整型(short).整型(int)和长整型(long),它们都可以定义整型变量,但是由于分配的内存空间不同,所能表示的数据的长度也不同. 我们可以定义并初始化一个整型变量: int a ...

  7. kafka broker Leader -1引起spark Streaming不能消费的故障解决方法

    一.问题描述:Kafka生产集群中有一台机器cdh-003由于物理故障原因挂掉了,并且系统起不来了,使得线上的spark Streaming实时任务不能正常消费,重启实时任务都不行.查看kafka t ...

  8. springboot WebMvcConfigurer配置静态资源和解决跨域

    前言 虽然现在都流行前后端分离部署,但有时候还是需要把前端文件跟后端文件一起打包发布,这就涉及到了springboot的静态资源访问的问题.不单只是静态资源打包,比如使用本地某个目录作为文件存储,也可 ...

  9. python中字典的建立

    一.字典由键key与值value构成. 如: a={'d':6,'f':'va'}print(a['f']) 上面代码简单建立字典,其中需要访问字典需要输入键值. 二.又比如需要在某个关键字中添加数据 ...

  10. 使用DES算法实现加密解密

    使用DES算法实现加密解密 我们常见的加密算法有DES.MD5.IDEA.AES等等,这篇随笔介绍使用DES算法实现加密解密 首先介绍一下DES算法: DES算法为密码体制中的对称密码体制,又被称为美 ...