协回返回类型表示:在导出类中覆盖基类的方法,可以返回基类方法的返回类型的某种导出类。...@Override tiger speak() { return new tiger(); } } panda继承了animal,并且重写了speak()方法,父类的speak...()方法的返回值类型是zoo,而子类重写speak()方法的返回值却是tiger,因为tiger继承了zoo,所以编译器不会报错。...因而也是一种合法的返回类型。
Java SE5中添加协变返回类型,表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型。...Mill { /** * 重写Mill的process()方法 * 协变返回类型允许返回更具体的Wheat类型,亦即此时的Wheat为协变返回类型 * @return...; System.out.println(g.getName()); // 因为是协变返回类型,所以可以向下转型 Wheat w = (Wheat) g;...协变返回类型允许返回更具体的Wheat类型 扩: 里氏代换原则(任何基类可以出现的地方,子类一定可以出现) 重写/覆盖规则: 1.重写方法不能比被重写方法限制有更严格的访问级别。...此处的Wheat即成了协变返回类型。 相关下载 点击下载
" 第一个 Signature #14 : 指向来常量池中的 String 类型的 ArrayList 记录了 toString 方法返回值的泛型信息。...(二) 对于挂载在函数返回类型上的泛型信息,可以通过如下方法来获取泛型信息: IntList.class.getDeclaredMethod("toStringList").getGenericReturnType...image.png 逆变后的继承关系 image.png 因此 Number 类型的 filter 过滤类可以认为是逆变之后的 Double 类型的 Filter 的子类型。...通过逆变,可以让泛型的约束变得更加宽松。 与协变不同,逆变放宽的是对父类的约束,而协变放宽的是对子类的约束。 但同样,逆变放宽类型约束是存在一定代价的: List<?...extends 通配符,使得子类型的泛型对象可以进行赋值,但同样会失去调用 add 存储功能时传递该泛型对象的能力: //泛型的协变 List<?
写在前面 ---- 和小伙伴分享一些java小知识点,主要围绕下面几点: 什么是逆变(contravariant)&协变(covariant)? 数组支持协变&逆变吗? 泛型支持协变&逆变吗?...说明对于数组的逆变来讲,是不支持逆变的,将父类强制转化为子类报类型转化异常,java并没有对这方面做限制。...对于协变和逆变是否支持 泛型不支持协变也不支持逆变,即不能把一个父类对象赋值给一个子类类型变量,相反也是同理。...super Integer> li = new ArrayList(); 关于协变逆变就和小伙伴分享到这里,嗯,还有协变逆变方法,这里要简单说明下 协变方法: 即子类的方法返回值的类型比父类方法要窄...//子类的doStuff()方法返回值的类型比父类方法要窄,即该方法为协变方法,也称多态。
我们知道,面向对象的继承中就蕴含可变性,当方法声明返回的类型为Stream时,可以在实现中返回一个FileStream类型,这里就存在一个隐式转换。...C# 2.0 确实是不支持的,但因为有了这样的需求,微软便适应地做出了改进,在 C# 4.0 中引入了泛型的协变性和逆变性 协变性 协变性指的是泛型类型参数可以从一个派生类隐式地转换为基类 C# 4.0...由于IComparer接口泛型参数只支持逆变,不支持协变,所以不能把IComparer类型隐式地转换为IComparer,所以会出现编译错误 协变和逆变的注意事项...并不是所有类型都支持泛型类型参数的协变和逆变性,下面总结了使用这两个特性时需要注意的地方 只有借口和委托才支持协变和逆变(如Func、Action),类或泛型方法的类型参数都不支持协变和逆变...协变和逆变只适用于引用类型,值类型不支持协变和逆变(因为可变性存在引用转换的过程,而值类型变量存储的就是对象本身,并不是对象的应用),所以List无法转换为IEnumerable<object
length // ok 复制代码 什么是抗变、双变、协变和逆变? Covariant 协变,TS对象兼容性是协变,父类 <= 子类,是可以的。子类 <= 父类,错误。...Bivariant 双向协变,函数参数的类型默认是双向协变的。父类 <= 子类,是可以的。子类 <= 父类,是可以的。...下面的代码在ts中是完全可以的,但在java等基于名义的语言则会抛错。...例如基本类型,联合类型等 类型别名不支持继承 类型别名不会创建一个真正的名字 类型别名无法被实现(implements),而接口可以被派生类实现 类型别名重名时编译器会抛出错误,接口重名时会产生合并...比如一个函数总是抛出错误,而没有返回值。或者一个函数内部有死循环,永远不会有返回值。函数的返回值就是never类型。 void, 没有显示的返回值的函数返回值为void类型。
泛型默认不支持型变 为了避免重蹈Java数组的覆辙,Java泛型显然不能再继续支持默认的型变。...总结来说,支持协变的集合只能取出元素,不能添加元素——疯狂Java讲义归纳的口诀是:协变只出不进!...对于更通用的泛型来说,对于支持协变的泛型,程序只能调用以泛型为返回值类型的方法;不能调用形参为泛型的方法。例如如下代码。...extends Number>也是支持协变的泛型,因此该类型的变量只能调用返回值为泛型的方法,不能调用形参为泛型的方法——如上①号代码所示。...对于更通用的泛型来说,对于支持逆变的泛型,程序只能调用以泛型为形参的方法;不能调用形参为返回值类型的方法(除非将返回值当成Object处理)。例如如下代码。
,具体如下: 变量或(类)成员初始值 参数默认值 函数返回值 这3类值都能提供直接的类型信息,进而确定目标类型。...,简单地讲: 协变(covariant):允许出现父类型的地方,也允许出现子类型,即里氏替换原则 逆变(contravariant):协变反过来,即允许出现子类型的地方,也允许出现父类型 双变(bivariant...):同时满足协变和逆变 不变(invariant或nonvariant):既不满足协变也不满足逆变 协变很容易理解,子类型兼容父类型,此外还具有一些(父类型不具备的)扩展属性或方法,因此用子类型换掉父类型后...,子类型允许类型之间有层级(继承)关系,从宽泛类型到特殊类型,而协变、逆变等关系就建立在这种类型层级之上: 协变:简单类型的层级关系保留到了复杂类型,这个复杂类型就是协变的,例如Animal是Cat的父类型...,而数组Animal[]也是Cat[]的父类型,所以数组类型是协变的 逆变:简单类型的层级关系到复杂类型中反过来了,这个复杂类型就是逆变的。
Java从入门到精通九(Java泛型) 泛型说明 使用泛型的好处 泛型类 泛型接口 引入类型通配符 不变,协变,逆变 用通配符支持协变和逆变(开挂行为) 泛型方法 泛型方法与可变参数 泛型上界下界 泛型数组...这样转换虽然在编译上没有报错,但是运行的时候便会抛出异常。 Integer类型是无法转换为String类型的。...引入类型通配符 这个我是查看了许多文章,然后其中说明的一个比较好的,我摘录一下具体的内容。 不变,协变,逆变 网上查看了许多资料就找到一篇用这几个名词。...简单来说,逆变就是比如A是B的父类,但是A可以继承B的类型匹配。。这样其实看起来有点逆向关系,所以叫做逆变,当然一般情况下,是不支持逆变的。...协变就是如果A是B的父类,B可以继承A的属性,也可以认为就是类型关系。 不变就是无论AB是和关系,都不能进行类型匹配。
协变返回类型 在 Java SE5 中,添加了协变返回类型,它表示在导出类中的被覆盖的方法可以返回基类方法的返回类型的某种导出类型。...对于上述协变返回类型的定义,读起来有些让人吐血,简单点,通过下面的程序理解协变返回类型: package com.hit.chapter8; /** * author:Charies Gavin...如上图所示,展示了使用协变返回类型后的效果。...在 Java SE5 之前,强制导出类中被覆盖的方法必须返回基类方法的返回类型,但是在增加协变返回类型之后,我们可以让在导出类中被覆盖的方法返回基类方法的返回类型的某种导出类型,也就是说可以返回更加具体的返回类型...例如上例中的kind()方法,在 Java SE5 之前,只能返回Plant,但是在使用协变返回类型之后,我们可以直接返回更加具体的Peony类型。
协变返回类型 在 Java SE5 中,添加了协变返回类型,它表示在导出类中的被覆盖的方法可以返回基类方法的返回类型的某种导出类型。...对于上述协变返回类型的定义,读起来有些让人吐血,简单点,通过下面的程序理解协变返回类型: package com.hit.chapter8; /** * author:Charies Gavin...Luoyangred extends Flower { Peony kind() { return new Peony(); } } [002] 如上图所示,展示了使用协变返回类型后的效果...在 Java SE5 之前,强制导出类中被覆盖的方法必须返回基类方法的返回类型,但是在增加协变返回类型之后,我们可以让在导出类中被覆盖的方法返回基类方法的返回类型的某种导出类型,也就是说可以返回更加具体的返回类型...例如上例中的kind()方法,在 Java SE5 之前,只能返回Plant,但是在使用协变返回类型之后,我们可以直接返回更加具体的Peony类型。
这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。...父子关系,在保证类型安全的基础上,增加了类型系统的灵活性。...这就是逆变,函数的参数有逆变的性质(而返回值是协变的,即子类型可以赋值给父类型)。...返回值的位置是协变的,即赋值的函数的返回值是被赋值的函数的返回值的子类型,此处 undefined 是 void 的子类型,所以不报错。...java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。
声明泛型变量,如 List lst = new ArrayList(); 注意点——泛型不支持协变 // S为P的子类,但List并不是List的子类...,也就是不支持协变 // 因此下列语句无法通过编译 List lst = new ArrayList(); // 而数组支持协变 P[] array = new S[10]; ...泛型类的类型参数可供实例方法、实例字段和构造函数中使用,不能用于类方法、类字段和静态代码块上。... number){} // JDK6后可通过不同的返回值类来解决冲突 // 对于Java语言而言,方法的签名仅为方法名+参数列表,但对于Bytecodes而言方法的签名还包含返回值类型...,根据不同的入参类型和对返回值进行类型转换的组合将导致不同的结果。
Java编译器的类型转换和类型检查 类型自动转换 既然上面所说Java会在编译时对泛型进行擦除,那么它要实现同一份泛型代码不同类型通用必然需要类型转换,事实上编译器也是这么干的,比如下面的这一段代码:...,而泛型中是不支持协变的,如上面的 List fruits=new ArrayList();//error 会产生编译时错误,之所以这么设计是因为数组支持运行时检查而集合类不支持运行时检查...不做任何限制,跟不用类型参数的 List 有什么区别呢? List list 表示 list 是持有某种特定类型的 List,但是不知道具体是哪种类型。那么我们可以向其中添加对象吗?...Kotlin 相比于Java 类型使用更为安全,泛型数组不支持协变(Java中支持)避免了数组运行时可能导致的类型转换异常,Kotlin中集合类和数组的泛型是有特定关键字来达到“协变”和“逆变”的效果的...,Kotlin 中相对于 Java 的通配符提出了一种新的定义:声明处型变(declaration-site variance)与类型投影(type projections) 这两种都是型变,不过一个是在声明处
坑亦有理 那我们就来分析下吧,报错的原因也很简单,编译器说 this@description 的类型是 Person,而 it.get 需要的参数类型是 out Person,什么鬼,这里居然还有协变的事儿...可问题是你老人家仔细瞅瞅,协变类型强转的事儿,真是没听说过.. 这就有意思了,我明明用的是 Person 的实例,怎么后面的属性的泛型参数是 out Person?...其实 Java 也有类似的操作,请看文章:Java中getClass方法的返回值类型 person::class 相当于 Java 的 person.getClass(),尽管这个方法的签名是这样的:...> getClass() 但这个返回值实际上是协变的: Class<?...当中)的处理方式是一致的,返回值都是协变的,但对于反射来说,Java 对参数类型要求几乎没有,而 Kotlin 则非常严格,这样会导致的问题就是 Kotlin 的反射使用起来有些难受。
更多详情请参考这篇文章,或者 Stack Overflow 上的这篇文章。 2. 可以使用不同的返回值类型来重载方法 以下代码是编译不过的,对吧? ?...是的,Java 不允许在一个类中通过不同的返回值类型和异常语句来重载方法。...这样提高了 JVM 的灵活性以实现各种语言特性。例如,可以用桥接方法(bridge method)来实现方法的协变返回类型,桥接方法和被重载的方法可以有相同的函数签名和不同的返回值类型。...因此,修改 JVM 是实现这个特性最简单的方法了(同时实现了协变式覆盖)。很聪明吧。 你明白语言的内部特性了吗? 这里有更多细节。 3. 这些都是二维数组 ? 是的,这是真的。...你也不懂复合赋值运算符 很诡异吗?让我们来看以下两段代码: ? 直觉上,他们是等价的吧?
extends 叫做 上界通配符,让Java泛型具有协变性,协变就是允许上面 的赋值是合法的。 它有两层意思: 其中?...super Button>,往里面添加 Button, 因此这种泛型类型声明称之为「消费者 Consumer」。 小结下,Java 的泛型本身是不支持协变和逆变的。 可以使用泛型通配符 ?...-使用关键字out来支持协变,等同于Java中的上界通配符? extends -使用关键字in来支持逆变,等同于Java中的上界通配符?...out interface Book interface EduBook:Book class BookStore{ //此处的返回类型,则为协变点 fun...实际上,我们可以声明一个inline函数,使其类型实参不被擦除,但是这在Java中是不行的。
我想使用数组来表示一个包含泛型的栈,但是以下代码编译报错。为什么? A. 不错的尝试。不幸的是,创建一个泛型数组在 Java 1.5里不支持。...你可以使用cast,比如下面的写法: 根本的原因是JAVA中的数组是“协变的(covariant)”,但是泛型并不是。...比如, String[] 是 Object[]的一种子类型,但是 Stack并不是 Stack 的一种子类型。 许多程序员认为“协变的”数组是JAVA在数据类型方面的一个缺点。...但是,如果我们不考虑泛型,“协变的”数组是有用的,比如实现 Arrays.sort(Comparable[]) 方法,然后当参数是 String[]时它也可以被正常调用。 Q....它将返回一个运行时错误。基础类型不允许它对应的装箱类型里的值是null。 Q. 为什么第一组打印的是 true,但是后面两组打印的是 false? A.
领取专属 10元无门槛券
手把手带您无忧上云