泛型型协变逆变

by Fabian Terh

由Fabian Terh

Java泛型类型简介:协变和逆变 (An introduction to generic types in Java: covariance and contravariance)

种类 (Types)

Java is a statically typed language, which means you must first declare a variable and its type before using it.

Java是一种静态类型的语言,这意味着您必须先声明一个变量及其类型,然后才能使用它。

For example: int myInteger = 42;

例如: int myInteger = 42;

Enter generic types.

输入通用类型。

通用类型 (Generic types)

Definition: “A generic type is a generic class or interface that is parameterized over types.”

定义 :“ 泛型类型是通过类型进行参数化的泛型类或接口。”

Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.

本质上,泛型类型允许您编写可与不同类型一起使用的泛型通用类(或方法),从而可以重复使用代码。

Rather than specifying obj to be of an int type, or a String type, or any other type, you define the Box class to accept a type parameter <;T>. Then, you can use T to represent that generic type in any part within your class.

您可以将Box类定义为接受类型参数< ; T>,而不是将obj指定为int类型, String类型或任何其他类型。 然后,CA n用t代表在类中的任何一部分泛型类型。

Now, enter covariance and contravariance.

现在,输入协方差和自变量。

协方差和自变量 (Covariance and contravariance)

定义 (Definition)

Variance refers to how subtyping between more complex types relates to subtyping between their components (source).

差异是指更复杂类型之间的子类型如何与其组件( 源 )之间的子类型相关。

An easy-to-remember (and extremely informal) definition of covariance and contravariance is:

协方差和协方差的一个易于记忆(非常非正式)的定义是:

  • Covariance: accept subtypes协方差:接受子类型
  • Contravariance: accept supertypes矛盾:接受超类型

数组 (Arrays)

In Java, arrays are covariant, which has 2 implications.

在Java中, 数组是covariant ,有2个含义。

Firstly, an array of type T[] may contain elements of type T and its subtypes.

首先,类型为T[]的数组可以包含类型T及其子类型的元素。

Number[] nums = new Number[5];nums[0] = new Integer(1); // Oknums[1] = new Double(2.0); // Ok

Secondly, an array of type S[] is a subtype of T[] if S is a subtype of T.

其次,类型的数组S[]是的子类型T[]如果S是的子类型T

Integer[] intArr = new Integer[5];Number[] numArr = intArr; // Ok

However, it’s important to remember that: (1) numArr is a reference of reference type Number[] to the “actual object” intArr of “actual type” Integer[].

但是,重要的是要记住:(1) numArr是引用类型Number[]对“ actual type” Integer[]的“ actual object” intArr

Therefore, the following line will compile just fine, but will produce a runtime ArrayStoreException (because of heap pollution):

因此,以下行将编译得很好,但将生成运行时ArrayStoreException (由于堆污染):

numArr[0] = 1.23; // Not ok

It produces a runtime exception, because Java knows at runtime that the “actual object” intArr is actually an array of Integer.

它产生一个运行时异常,因为Java在运行时知道“实际对象” intArr实际上是Integer的数组。

泛型 (Generics)

With generic types, Java has no way of knowing at runtime the type information of the type parameters, due to type erasure. Therefore, it cannot protect against heap pollution at runtime.

对于泛型类型,由于类型擦除,Java无法在运行时知道类型参数的类型信息。 因此,它无法在运行时防止堆污染。

As such, generics are invariant.

因此,泛型是不变的。

ArrayList<Integer> intArrList = new ArrayList<>();ArrayList<Number> numArrList = intArrList; // Not okArrayList<Integer> anotherIntArrList = intArrList; // Ok

The type parameters must match exactly, to protect against heap pollution.

类型参数必须完全匹配,以防止堆污染。

But enter wildcards.

但是输入通配符。

通配符,协方差和逆方差 (Wildcards, covariance, and contravariance)

With wildcards, it’s possible for generics to support covariance and contravariance.

使用通配符,泛型有可能支持协方差和协方差。

Tweaking the previous example, we get this, which works!

调整前面的示例,我们得到了这个,它有效!

ArrayList<Integer> intArrList = new ArrayList<>();ArrayList<? super Integer> numArrList = intArrList; // Ok

The question mark “?” refers to a wildcard which represents an unknown type. It can be lower-bounded, which restricts the unknown type to be a specific type or its supertype.

问号“?” 表示代表未知类型的通配符。 它可以是下界的,这将未知类型限制为特定类型或其超类型。

Therefore, in line 2, ? super Integer translates to “any type that is an Integer type or its supertype”.

因此,在第2行, ? super Integer ? super Integer转换为“任何为Integer类型或其超类型的类型”。

You could also upper-bound the wildcard, which restricts the unknown type to be a specific type or its subtype, by using ? extends Integer.

您还可以使用? extends Integer来限制通配符的范围,通配符将未知类型限制为特定类型或其子类型? extends Integer ? extends Integer

只读和只写 (Read-only and write-only)

Covariance and contravariance produce some interesting outcomes. Covariant types are read-only, while contravariant types are write-only.

协方差和自变量产生一些有趣的结果。 协变类型是只读的,而协变类型是只写的。

Remember that covariant types accept subtypes, so ArrayList<? extends Number> can contain any object that is either of a Number type or its subtype.

还记得协变类型接受子类型ArrayList<? extends Numb ,所以ArrayList<? extends Numb ArrayList<? extends Numb ER>可以包含任何对象,或者是of a数字类型或子类型。

In this example, line 9 works, because we can be certain that whatever we get from the ArrayList can be upcasted to a Number type (because if it extends Number, by definition, it is a Number).

在此示例中,第9行有效,因为我们可以确定从ArrayList中获得的任何内容都可以转换为Number类型(因为如果它扩展Number ,顾名思义,它就是 Number )。

But nums.add() doesn’t work, because we cannot be sure of the “actual type” of the object. All we know is that it must be a Number or its subtypes (e.g. Integer, Double, Long, etc.).

但是nums.add()不起作用,因为我们不能确定对象的“实际类型”。 我们所知道的是它必须是一个Number或其子类型(例如Integer,Double,Long等)。

With contravariance, the converse is true.

在相反的情况下,反之亦然。

Line 9 works, because we can be certain that whatever the “actual type” of the object is, it must be Integer or its supertype, and thus accept an Integer object.

第9行行得通,因为我们可以确定,无论对象的“实际类型”是什么,它都必须是Integer或它的超类型,因此可以接受Integer对象。

But line 10 doesn’t work, because we cannot be sure that we will get an Integer. For instance, nums could be referencing an ArrayList of Objects.

但是第10行不起作用,因为我们无法确定是否会获得Integer 。 例如, nums可以引用Objects的ArrayList。

应用领域 (Applications)

Therefore, since covariant types are read-only and contravariant types are write-only (loosely speaking), we can derive the following rule of thumb: “Producer extends, consumer super”.

因此,由于协变量类型是只读的,而协变量类型是只写的(松散地说),我们可以得出以下经验法则: “生产者扩展,消费者超级”

A producer-like object that produces objects of type T can be of type parameter <? extends T>, while a consumer-like object that consumes objects of type T can be of type parameter <? super T>.

产生类型T对象的类似生产者的对象可以是参数<? extends <? extends T>,而消费类对象消费 T型可以是参数meter <? 超级T>。

翻译自: https://www.freecodecamp.org/news/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2/

泛型型协变逆变

泛型型协变逆变_Java泛型类型简介:协变和逆变相关推荐

  1. java协变返回类型_Java中的协变返回类型

    java协变返回类型 协变返回类型 (Covariant return type) The covariant return type is that return type which may va ...

  2. java数组逆序_Java 数组的排序、逆序

    数组的排序.逆序测试数据 public static void main (String[] args) { // 数组逆序 int[] arr = {1,2,3,4,5,6,7}; reverse( ...

  3. 三相全桥整流 逆变 matlab,三相桥式有源逆变电路的MATLAB建模仿真

    电子技术0 Electronictechnology 三相桥式有源逆变电路的MATLAB建模仿真 文/翟羽翟凯骆蒙 对三相桥式有源逆变电路逝.行公绍,并在matlab/simulink 要 中这立三相 ...

  4. 教你如何攻克Kotlin中泛型型变的难点(下篇)

    简述: 前几天我们一起为Kotlin中的泛型型变做了一个很好的铺垫,深入分析下类型和类,子类型和子类之间的关系.什么是子类型化关系以及型变存在的意义.那么今天将会讲点更刺激的东西,也就是Kotlin泛 ...

  5. 教你如何攻克Kotlin中泛型型变的难点(应用篇)

    简述: 这是泛型型变最后一篇文章了,也是泛型介绍的最后一篇文章.顺便再扯点别的,上周去北京参加了JetBrains 2018开发者日,主要是参加Kotlin专场.个人感觉收获还是挺多的,bennyHu ...

  6. ML之FE:数据处理—特征工程之特征三化(标准化【四大数据类型(数值型/类别型/字符串型/时间型)】、归一化、向量化)简介、代码实现、案例应用之详细攻略

    ML之FE:数据处理-特征工程之特征三化(标准化[四大数据类型(数值型/类别型/字符串型/时间型)].归一化.向量化)简介.代码实现.案例应用之详细攻略 目录 真正意义的标准化与归一化 1.标准化/Z ...

  7. 我国民用高分辨率光学传输型立体测图卫星-资源三号简介(文末附带示例数据)

    我国民用高分辨率光学传输型立体测图卫星-资源三号简介 目前资源三号由资源三号01星和资源三号02星组成: 资源三号01星(ZY3-01)是我国首颗民用高分辨率光学传输型立体测图卫星,于2012年1月9 ...

  8. 机器人图形变变变_中班数学活动——图形变变变 教案

    版权声明:以上文章中所选用的图片及文字来源于网络以及用户投稿,由于未联系到知识产权人或未发现有关知识产权的登记,如有知识产权人并不愿意我们使用,如果有侵权请立即联系:55525090@qq.com,我 ...

  9. QGraphicsView加入到布局,所在的窗口变大,视图和场景都变大,使场景中的矩形也变大

    需求 窗口变化时,窗口中的矩形框也变化. 效果展示 当窗口变大时其矩形框也变大 要求绿色矩形框与蓝色背景的边距始终为10. 代码 直接上项目的代码. 项目结构 各文件的代码 main.cpp #inc ...

最新文章

  1. 新浪php面试题目,新浪php的面试题 收集
  2. 确定关键质量的5大原则
  3. ASP.NET MVC 3 Internationalization
  4. grpc简单使用 java_gRPC学习记录(四)-官方Demo - Java 技术驿站-Java 技术驿站
  5. tcp分包传图片 如何还原_技术控丨超详细解析TCP重传机制
  6. OpenShift 4 - 安装3Scale API Management环境
  7. 敏捷开发生态系统系列之四:计划跟踪II(自组织团队-开发团队自己估算-PO挑战估算-同行压力)...
  8. 什么是Bootstrap?
  9. 【论文笔记】Depth Map Prediction from a Single Image using a Multi-Scale Deep Network
  10. 前端内容占位技术分享
  11. 全国计算机二级c语言题库,计算机二级c语言题库及答案
  12. mac电脑安卓开发环境搭建
  13. rs485全双工中只接一组_关于RS485接口的十八个经典问答!看你能答出几个!
  14. 解决验证码不显示问题
  15. Android基于opencv4.6.0实现人脸识别功能
  16. ps污点修复画笔用法和案例:去除脸上痘痘
  17. 流畅的python第六章 使用一等函数设计模式
  18. qt 引发了异常: 写入访问权限冲突。this 是 0x7FF700000000。
  19. SQL中将年月日, DATE_FORMAT()格式转换指定格式
  20. 【gcc】centos安装gcc

热门文章

  1. java接口的修饰符可以为,附架构师必备技术详解
  2. 百度、阿里、滴滴、新浪的面试心经总结,源码+原理+手写框架
  3. 安卓开发面试技能介绍,来一份全面的面试宝典练练手,不吃透都对不起自己
  4. 使用thinkPHP做注册程序的实例
  5. 浪里个浪 FZU - 2261
  6. Robot Framework自动化测试(一)--- 安装
  7. iOS 应用内跳转到appstore里下载
  8. 一个简单易用的导出Excel类
  9. 区块链监管的一年,剥离“币”的区块链技术该何去何从?
  10. Python高级网络编程系列之基础篇