Java中芬兰湾的科特林的协变与逆变是什么

  介绍

小编给大家分享一下Java中芬兰湾的科特林的协变与逆变是什么,希望大家阅读完这篇文章后大所收获、下面让我们一起去探讨吧!

Java基础教程栏目今天介绍芬兰湾的科特林的协变与逆变。

前言

为了更好地理解芬兰湾的科特林和Java中的协变与逆变,先看一些基础知识。

普通赋值

在Java中,常见的赋值语句如下:

 A=b;复制代码

赋值语句必须满足的条件是:左边要么是右边的父类,要么和右边类型一样,即的类型要“大”于b的类型,比如<代码>对象o=新的字符串(“s");>

除了上述最常见的赋值语句,还有两种其他的赋值语句:

函数参数的赋值
公共空有趣(一){}//调用处赋值B B=new ();   有趣的(b);复制代码

在调用有趣的(b)方法时,会将传入的b b实参赋值给形参一个,即<代码> A=b>

函数返回值的赋值
公众一个有趣的(){   B B=new ();返回b;   }   复制代码

函数返回值类型接收实际返回类型的值,实际返回类型B B相当于赋值给了函数返回值类型的,即B B赋值给了一个,即<代码> A=B>

所以,无论哪种赋值,都必须满足左边类型比;右边类型,即在b .

Java中的协变与逆变

有了前面的基础知识,就可以方便地解释协变与逆变了。

如果类比;类B,经过一个变化反式后得到的反式(A)与反式(B)依旧满足反式(A)在反式(B),那么称为<强>协变

逆变则刚好相反,如果类比;类B,经过一个变化反式后得到的反式(A)与反式(B)满足反式(B)比;反式(A),称为<>强逆变

比如大家都知道Java的数组是协变的,假如比;B,那么有[]比;B[],所以B[]可以赋值给一个[]。举个例子:

 Integer [] num=new Integer [] {};
  对象[]o=num;//可以赋值,因为数组的协变特性所以由对象比;整得到对象[]比;整数[]复制代码

但是Java的泛型则不满足协变,如下:

Listl=new ArrayList<在();   Listo=l;//这里会报的错,不能编译复制代码

上述代码报的错,就是因为,虽然对象比;整数,但是由于泛型不满足协变,所以<代码> List 比;<代码> List 赋值给List

Java中泛型如何实现协变与逆变

从前面我们知道,在Java中泛型是不支持型变的,但是这会产生一个让人很奇怪的疑惑,也是很多讲泛型的文章中提到的:

如果B是A的子类,那么List就应该是List的子类呀!这是一个非常自然而然的想法!

但是很抱歉,由于种种原因,Java并不支持。但是,Java并不是完全抹杀了泛型的型变特性,Java提供了& lt; ?T>延伸;和& lt; ?超级T>使泛型拥有协变和逆变的特性。

& lt; ?T>延伸;与& lt; ?超级T>

& lt; ?T>延伸;称为上界通配符& lt; ?超级T>称为下界通配符。使用上界通配符可以使泛型协变,而使用下界通配符可以使泛型逆变。

比如之前举的例子

Listl=new ArrayList<在();   Listo=l;//这里会报的错,不能编译复制代码

如果使用上界通配符,

Listl=new ArrayList<在();   List<?Object>延伸;o=l;//可以通过编译复制代码

这样,List<?Object>延伸;的类型就大于List的类型了,也就实现了协变。这也就是所谓的“子类的泛型是泛型的子类”。

同样,下界通配符& lt; ?超级T>可以实现逆变,如:

公共List<?超级Integer>有趣的(){
  Listl=new ArrayList<在();返回l;
  }复制代码 

上述代码怎么就实现逆变了呢?首先,对象比;整数;另外,从前言我们知道,函数返回值类型必须大于实际返回值类型,在这里就是<代码> List<?超级Integer> 比;<代码> List

从上面可以看的出,& lt; ?T>延伸;中的上界是T,也就是说& lt; ?T>延伸;所泛指的类型都是T的子类或T本身,所以T大于& lt; ?T>延伸;灵活;?超级T>中的下界是T,也就是说& lt; ?超级T>所泛指的类型都是T的父类或T本身,所以& lt; ?超级T>,大于t .

Java中芬兰湾的科特林的协变与逆变是什么

Copyright © 2020-2023 feiqueyun.cn. All Rights Reserved. 肥雀云_南京肥雀信息技术有限公司版权所有 南京肥雀信息技术有限公司 苏ICP备16063723号-5