写在前面 ---- 和小伙伴分享一些java小知识点,主要围绕下面几点: 什么是逆变(contravariant)&协变(covariant)? 数组支持协变&逆变吗? 泛型支持协变&逆变吗?...下面们结合代码就数组和泛型的协变和逆变进行分析 我们来看一段代码 package com.liruilong; import java.util.Arrays; /** * @Project_name...,这些封装类可以出现在Number类定义的数组中,说明子类可以替换了父类,即数组是满足协变的。...Object类,即所有类的父类,希望是可以通过父类来覆盖代替子类,但是直接编译报错,说明数组是不支持直接逆变的 Error:(17, 30) java: 不兼容的类型: java.lang.Object...说明对于数组的逆变来讲,是不支持逆变的,将父类强制转化为子类报类型转化异常,java并没有对这方面做限制。
协回返回类型表示:在导出类中覆盖基类的方法,可以返回基类方法的返回类型的某种导出类。...tiger speak() { return new tiger(); } } panda继承了animal,并且重写了speak()方法,父类的speak()方法的返回值类型是zoo
背景 文接上回,说到过Java的泛型擦除问题,这块我又联想到一个有意思的考点泛型的协变和逆变。...一、协变 首先Java的数组是协变的,所以假设A是B的父类,那么A[]是可以保存A或者B的对象的,并且A[]是B[]的父类。 ,写谁都会写,子类型限定。...根因是Java的泛型没有协变类型,无法关联起来,也就没有关系。 利用通配符,?代表子类,T为父类。 常见的例子比如,List协变,消费者为逆变。 针对于生产者,可取,有上界;针对于消费者,可存,有下界。...理解它,也可以通过Java的继承关系, 假设存在继承关系Object-》T、T-》A、T-》B; 即T为A、B的父类,协变面向子类;逆变面向Object,它是所有对象的父类。
导读 泛型是Java最基础的语法之一,众所周知:出于安全原因,泛型默认不能支持型变(否则会引入危险),因此Java提供了通配符上限和通配符下限来支持型变,其中通配符上限就泛型协变,通配符下限就是泛型逆变...由于来自早期的设计,所以Java的数组默认就支持型变(Variance):只要A是B的子类,那么A[]就相当于B[]的子类,比如Integer是Number的子类,因此Integer[]就相当于Number...泛型默认不支持型变 为了避免重蹈Java数组的覆辙,Java泛型显然不能再继续支持默认的型变。...协变:通配符上限 为了让泛型支持型变,Java引入了通配符上限语法:如果A是B的子类,那么List相当于是List协变的集合只能取出元素,不能添加元素——疯狂Java讲义归纳的口诀是:协变只出不进!
Java SE5中添加协变返回类型,表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型。...Wheat类型,亦即此时的Wheat为协变返回类型 * @return */ Wheat process(){ return new Wheat();...; System.out.println(g.getName()); // 因为是协变返回类型,所以可以向下转型 Wheat w = (Wheat) g;...协变返回类型允许返回更具体的Wheat类型 扩: 里氏代换原则(任何基类可以出现的地方,子类一定可以出现) 重写/覆盖规则: 1.重写方法不能比被重写方法限制有更严格的访问级别。...此处的Wheat即成了协变返回类型。 相关下载 点击下载
通过协变和逆变原则 协变与逆变(covariance and contravariance)是在计算机科学中,描述具有父/子型别关系的多个型别通过型别构造器、构造出的多个复杂型别之间是否有父/子型别关系的用语...维基百科上关于协变和逆变的解释有点晦涩难懂。...但在TS中,参数类型是双向协变的(详见下文3.1小节),如果项目里开启了"strict": true,意味着,会来带开启 strictFunctionType ,此时,才按照逆变处理 双向协变 在老版本的...TS 中,函数参数是双向协变的。...设置之后,函数参数就不再是双向协变的了。
协变 在 Java 中,数组是协变的,也就是说,假设有一个基类 Person 和一个 Person 的子类 Student。...也就是说,给协变的数组的单元赋值的时候出错了。这个错误本来应该由编译器发现并指出,但 Java 将对这一错误的防止延后到了运行时期,错过了编译期的检查。...在 Java 的早期版本中,工程师们因为时间紧迫而选择暂时不添加泛型在 Java 的语法中,这导致 Java 的数组没法使用泛型,在这种情况下,如果数组的型变是不变,那么要写一些通用的数组操作方法就变得困难...语义与协变的情况是类似的。 于是,Scala 和 Java 的型变标记可以进行如下总结 3: Scala Java 解释 +T ?...而 get 方法的类型显然是 () => T。所以从单元中获取元素这个操作上来看,数组在其元素的类型上协变。
参考链接: Java covariant返回类型 协变返回类型:子类覆写了父类的一个方法,子类中方法的返回值类型可以是父类方法返回值类型的子类。...示例代码(Java编程思想)如下所示:子类WheatMill覆写了父类Mill的process方法,子类proces方法的返回值Wheat是父类proces方法返回值Grain的子类。
out关键字指明类型参数是协变的 上面这段代码,dog是派生自Animal类,它是可以直接赋值给Animal类的,但此代码却产生错误,这是因为委托也是类型,Factory和Factory<Animal...)(派生类只是用来输出值) “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。...“协变”->”和谐的变”->”很自然的变化”->string->object :协变 协变在委托声明中加入out关键字,表示派生类只是用来输出值,避免出现由delegate派生类是平级,它们定义的变量无法相互赋值产生的问题...协变(out)是将派生类对象的引用传入到基类对象,输出派生类的值 逆变(in)是将基类对象的引用传入到派生对象,派生对象只能操作基类部分 接口的协变和逆变 1️⃣ 接口的协变 using System...DoSomething(father); } } 3️⃣ 协变和逆变的隐式强制转换 编译器自动识别某个已构建的委托是协变或是逆变并且自动进行强制转换 using System;
msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。 “逆变”则是指能够使用派生程度更小的类型。 解释的很正确,大致就是这样,不过不够直白。 ...上面是个人对协变和逆变的理解,比起记住那些派生,类型,原始指定,更大,更小之类的词语,个人认为要容易点。 ...正因如此,所以微软新增了两个关键字:Out,In,下面是他们的msdn解释: 协变的英文是:“covariant”,逆变的英文是:“Contravariant” 为什么Microsoft选择的是”Out...我个人的理解: 因为协变和逆变的英文太复杂了,并没有体现协变和逆变的不同,但是out 和 in 却很直白。...想要回答这个问题需要在回头看看Clr via C# 关于泛型和接口的章节了,我就不解释了, 答案是不可以。 上面演示的是协变,接下来要演示下逆变。
之后又想到了其他一些相关的东西,除了简单地分析如何通过Emit实现EventHandler的类型转换之外,还加上关于Delegate“协变”与“逆变”的一些东西,算是对前一篇文章的完善。...目录 一、从Delegate的“协变”与“逆变”说起 二、EventHandler是否换一种定义方式更好?...四、通过Emit实现EventHandler的类型转换 五、最简单的转换方式 一、从Delegate的“协变”与“逆变”说起 根据Delegate“协变”与“逆变”的原理,对于两个具有相同声明的两个...我们在定义泛型Delegate的时候可以利用C#“协变”与“逆变”,使类型为A对象能够赋值给类型为B的变量。...EventArgs e); 2: public delegate void EventHandler(object sender, TEventArgs e); 根据Delegate“协变
前言 在.NET 4之前,泛型接口是不变的。.NET 4通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展。协变和抗变指对参数和返回值的类型进行转换。 ...我们来看下到底什么是协变什么是抗变: 如果某个返回的类型可以由其基类替换,那么这个类型就是支持协变的 如果某个参数类型可以由其派生类替换,那么这个类型就是支持逆变(抗变)的。...这里就比较接近泛型接口的协变和抗变的概念了。...理解泛型接口的协变和抗变(in、out) 我们下面来看看泛型接口的协变及抗变的例子: 首先我们看下协变,在C#高级编程(第十一版)中指出,如果泛型类型用out关键字标注,泛型接口就是协变的。...协变:(使用关键字out)返回类型可以由其基类所替代的时候,就是支持协变的。 抗变(逆变):(使用关键字in)传入参数类型可以由其派生类所代替的时候,就是支持抗变(逆变)的。
Kotlin 的型变分为逆变、协变和不变。...2.1 协变 如果 A 是 B 的子类型,并且Generic 也是 Generic 的子类型,那么 Generic 可以称之为一个协变类。...2.2.1 Java 下界通配符 Java 的逆变通过下界通配符实现。 下面的代码因为是协变的,无法添加新的对象。...2.3 不变 默认情况下,Kotlin 中的泛型类是不变的。 这意味着它们既不是协变的也不是逆变的。 例如 MutableList,它可读可写,泛型没有使用in、out。 三....总结 本文从 Kotlin 的类、类型引出了型变。介绍了 Kotlin 的协变、协变和不变的概念和特性,以及 Java 的上界通配符、下界通配符。 该系列的相关文章: Kotlin 泛型之类型擦除
我们知道子类转换到父类,在C#中是能够隐式转换的。这种子类到父类的转换就是协变。而另外一种类似于父类转向子类的变换,可以简单的理解为逆变。...,f(x)表示类型转换,≤表示继承关系(比如,A≤B表示A是由B派生出来的子类) 当A≤B时,若f(x)是逆变的,则f(B)≤f(A)成立; 当A≤B时,若f(x)是协变的,则f(A)≤f(B)成立;...令List成为List子类的变化,我们叫做协变,和string与Object的父子关系是相同的;反之,令List成为List子类的变化,我们叫做逆变...,和string与Object的父子关系是相反的; 协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。...//数组-逆变 //数组的协变使派生程度更大的类型的数组能够隐式转换为派生程度更小的类型的数组。
前言 在引用类型系统时,协变、逆变和不变性具有如下定义。 这些示例假定一个名为 Base 的基类和一个名为 Derived的派生类。...固定泛型类型参数既不是协变,也不是逆变。 你无法将 List 的实例分配给 List 类型的变量,反之亦然。 以上来自于官方文档对协变、逆变、不变性的解释 为啥C#需要协变和逆变?...在C#中,目前只有泛型接口和泛型委托可以支持协变和逆变, 协变(Covariance) 内置的泛型协变接口,IEnumerator、IQuerable、IGrouping<Tkey, TElement...、方法或者委托的输入参数 当要进行类型转换,占位符T要转换的目标类型也必须是其子类,上述例子则是FooBase转为Foo 总结 协变和逆变只对泛型委托和泛型接口有效,对普通的泛型类和泛型方法无效 协变和逆变的类型必须是引用类型...,因为值类型不具备继承性,因此类型转换存在不兼容性 泛型接口和泛型委托可同时存在协变和逆变的类型参数,即占位符T 参考 泛型中的协变和逆变 | Microsoft Docs 《你必须知道的.NET(第2
—沃茨•其索特 1 什么是协变与逆变 刚开始看到协变(Covariance)和逆变(Contravariance)的时候,差点晕菜,反复查了一些资料,才稍有些自己的体会,难免有理解不对的地方,欢迎指出...那么我们就可以这么来解释协变和逆变了: 协变: 如果说 List 也是 List的subtype,也就是衍生类型的关系和原来类型( Cat 与 Animal)的关系是一致的,那我们就说...List 是和它的原来类型协变(共同变化)的。...2 为什么要了解协变与逆变?...也就是说函数的参数是逆变的。 得到的结论是: 函数的参数是逆变的,返回值是协变的。 我们知道了变化的规则,就能判断出类型的关系,就可以知道一个类型是否可以替换另外一个类型。
image.png 因此 Number 类型的 filter 过滤类可以认为是逆变之后的 Double 类型的 Filter 的子类型。...通过逆变,可以让泛型的约束变得更加宽松。 与协变不同,逆变放宽的是对父类的约束,而协变放宽的是对子类的约束。 但同样,逆变放宽类型约束是存在一定代价的: List<?...再也无法从函数返回值中得到这个繁星的类型 Double number = list.get(0); //编译不通过 Object number = list.get(0); //只能作为顶层级的Object类 泛型的协变使用的是...extends 通配符,使得子类型的泛型对象可以进行赋值,但同样会失去调用 add 存储功能时传递该泛型对象的能力: //泛型的协变 List list = new ArrayList(); list.get(0); //无法进行get 逆变与协变的使用场景: 当一个对象只作为泛型的生产者,也就是只取泛型的情况下
在一些类型系统中,例如 Java,这些概念是显式嵌入到语言中的,例如使用extends关键字表示协变,使用super关键字表示逆变。...例如,如果你有一个Animal类型的数组,并且你有一个Dog类型的对象(假设Dog是Animal的子类型),那么你应该能够将Dog对象添加到Animal数组中。这就是协变。...[]的子类型,所以数组是协变的。...协变:类型的向下兼容性 协变是类型系统中的一个基本概念,它描述的是类型的“向下兼容性”。...>的子类型 逆变(Contravariance) 逆变是协变的反面。
本文简述了 C# 中协变和逆变的一些知识 在 C# 中, 协变 和 逆变 能够实现 数组类型 和 委托类型 的隐式引用转换, .NET Framework 4 (包括)以后, C# 也开始支持在...泛型接口 和 泛型委托 中使用协变和逆变,下面的内容也主要围绕泛型类型参数的协变和逆变来进行讲解....什么是协变? 所谓协变(Covariance),是指能够使用比原始指定的类型派生程度更大的类型,简单理解就是 子类转为父类 这种变化....小结: 协变和逆变用于隐式引用转换 协变的关键字为 out,被其修饰的参数类型只能用于输出参数 逆变的关键字为 in,被其修饰的参数类型只能用于输入参数 子类总是可以安全的转为父类是保证协变和逆变类型安全的统一前提...参考资料 协变和逆变 (C#) 泛型中的协变和逆变 深入理解 C# 协变和逆变 理解 C# 泛型接口中的协变与逆变
领取专属 10元无门槛券
手把手带您无忧上云