Java泛型中逆变和协变的概念

发布时间:2021-08-30 11:00:29 作者:chen
来源:亿速云 阅读:142

本篇内容主要讲解“Java泛型中逆变和协变的概念”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型中逆变和协变的概念”吧!

正文

OK,今天5分钟短文就让咱们聊一聊逆变和协变这俩个概念。

1、基础概念

其实它们俩的概念很好理解。接下来让我们仔细读一遍下边的这一段话:

逆变与协变用来描述类型转换后的继承关系。如果A、B表示类型,f(...)表示类型转换,≤表示继承关系(比如,A≤B表示A是B的子类)

如果f(...)是逆变的,那么当A≤B时则f(B)≤f(A)成立

如果f(...)是协变的,那么当A≤B时则f(A)≤f(B)成立

额外补充一条:如果f(...)是不变的,那么当A≤B时则f(B)与f(A)没有任何关系

2、代码场景

如果大家充分理解了上边的话,其实就能想到咱们日常代码中的例子:数组就是一种协变;泛型是不变的。上代码:

public class A extends B {}  public class B {}     public void test() {  B[] arrs = new A[66];  List<B> list = new ArrayList<A>();  }

这段代码是编不过的:

Java泛型中逆变和协变的概念

因为数组是协变的,所以 A[]是 B[]的子类;而泛型不是,所以 List并不是 List的子类。

3、通配符的意义

因为这个原因的存在,所以才有了通配符。

3.1、协变-上限通配符

代码改成这个样子就可以正常编译了:

Java泛型中逆变和协变的概念

通配符的存在,让泛型产生了协变,让 List可以变成 List的子类。不过我猜经验丰富的同学已经知道,这样搞“没什么卵用”,因为:

Java泛型中逆变和协变的概念

我们发现,这样搞完。对于 list变量来说,我们只能 get()不能  add()!一时接受不了?其实这里也很好理解,协变之后对于list来说,我可以指向很多 List的子类。

假设此时我们可以随意 add(),那么对于运行期来说简直是灾难:因为我可以随意的 add(newA());add(newC())。如果这种情况存在那么我  get()的时候,是不是只能把它当做 B来使用,因为这里有可能有 A也有可能有 C...

这样搞完全没有意义...因此也就有了下边的内容:逆变-下限通配符

3.2、逆变-下限通配符

直接上代码:

public class A extends B {}  public class B {}  public class C extends B {}  public class D extends A {}     public void test2(List<? super A> list){  list.add(new A());  list.add(new B());  list.add(new C());  list.add(new D());  }

此时我们会发现:我们可以 add(), A及其子类。而这种实现就脱胎于咱们逆变这个概念。

Java泛型中逆变和协变的概念

到此,相信大家对“Java泛型中逆变和协变的概念”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. kotlin中的高级特性--协变与逆变(反变)
  2. .Net--协变、逆变

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Java8中的接口和抽象类到底有什么区别

下一篇:js正则表达式的search方法讲解

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》