Kotlin 和 Java 泛型的缺陷和应用场景

Hi 大家好,我是 DHL。大众号:ByteCode ,专心共享有趣硬核原创内容,Kotlin、Jetpack、功能优化、体系源码、算法及数据结构、动画、数据结构c语言版第二版课后答案大厂面经

全文分elements中文翻译视频版文字版

  • 文字版: 文字侧重细节和深度,有些知识点,视频欠好表达,文动画片少儿小猪佩奇字描述的愈加准确
  • 视频版: 视频会愈加的直观,看完文字版,在看视频,知识点会愈加清楚

视频版 bilibili 地址:h数据结构c语言版第二版课后答案ttps://b23.tv/AdLtUGf

泛型关于每个开发者而言并不陌生,平常在项目中会常常见到,可是有很多小伙伴们,每次见到通配符 ? extends? superoutin 都傻傻分不清楚它们的区别,以及在什么情况下运用。

经过这篇文章将会学习的到以下内容。

  • 为什么要有泛型
  • Kotlin 和 J动画制作软件ava 的协变
  • Kotlin 和 Java 的逆变
  • 通配符 ? ex数据结构实验报告tends? superoutin 的区别和运用场景
  • Koelementary是什么意思tlin 和 Java 数组协变google商店的不同之处
  • 数组协变的缺点
  • 协变和源码之家逆变的运用场景

为什么要有泛型

在 Java 和 Kotlin 中咱们常用调集( Lgoogle谷歌搜索主页istSe数据结构知识点总结tMap 等等)源码编程器来存储数据,而在调集中可能存动画电影储各种类型的数据,现在咱们有四种数据类型 IntFloatDoubleNumber,假设没有泛型,咱们elementary需求创立四个调集类来存储对应的数据。

class IntList{ }
class Floatlist{}
class DoubleList{}
class NumberList{}
......
更多

如果有更多的类型,就需求创立更多的调集类来保存对应的数据,这显示是不可能的,而泛型是一个 “万数据结构c语言版第二版课后答案能的类型匹配器”,一起有能让编译器确保类型安全。

泛型数据结构实验报告将详细的类型( IntFloatDouble 等等)声明的时分运用符号来替代,运用的时分,才指定详细的类型。

// 声明的时分运用符号来替代
class List<E>{
}
// 在 Kotlin 中运用,指定详细的类型
val data1: List<Int> = List()
val data2: List<Float> = List()
// 在 Java 中运用,指定详细的类型
List<Integer> data1 = new List();
List<Float> data2 = new List();

泛型很好的帮咱们element滑板解决了上面的问题,可是随之而来出现了新的问题,咱们都知道 IntFloatDoubleNumber 子类型, 因而下面的代码是能够正常运转的。源码编程器

// Kotlin
val number: Number = 1
// Java
Number number = 1;

咱们花三秒钟考虑一下,下面的代码是否能够正常编译。

List<Number> numbers = new ArrayList<Integer>();

答案是不能够,正如下图所示,编译会犯错。

Kotlin 和 Java 泛型的缺点和运用场景

这也就说明了泛型是不可变的,IDE 以为 ArrayList<Integer> 不是 List<Numberelements> 子类型,不允许这么赋值,那么如何解决这个问google商店题呢,这就需求用到协变了,协变允许上面的赋值是合法的。

Kotlin 和 Java 的协变

  • 在 Java 顶用通配符 ? extends T 表明协变,exte动画片少儿小猪佩奇nds 束缚了父类型 T,其间 ? 表明不知道源码之家类型,比方 ? extends Number,只需声明时传入的类型是 Numb动画片熊出没er 或许 Number 的子类型都能够
  • 在 Kotlin 中关键字 out T 表明协变,意义和 Java 相同

现在咱们将上面的代码修正一下,在花三秒钟考虑一下,下面的代码是否能够正常编译。

// kotlin
val numbers: MutableList<out Number> = ArrayList<Int>()
// Java
List<? extends Number> numbers = new ArrayList<Integer>();

答案是能够正常编译,协变通配符 ? extendsgoogle Number 或许 out Number 表明接受 Nu动画头像mber 或许 Nelementary翻译umber 子类型为目标的调集,协变放宽了对数据类google中国型的束缚,可是放宽是有价google商店值的,咱们在花三秒钟考虑一下,下面的代码是否能够正常编译。

// Koltin
val numbers: MutableList<out Number> = ArrayList<Int>()
numbers.add(1)
// Java
List<? extends Number> numbers = new ArrayList<Integer>();
numbers.add(1)

调用 add() 办法会编译失利,尽管协变放宽了对数据类型的束缚,能够接受 Number 或许 Number 子类型为目标的调动画专业集,可是价值是 无法增加元素,只能获取元素,因而协变只能作为生产者,向外供给数据。

为什么无法增加元素

由于 ? 表明不知element翻译道类型,所以编译器也不知道会往调集中增加什么类型的数据,因而干脆不允许往调集动画片熊出没中增加元素。

可是如果想让上面的代码编译经过,想往调集中增加元素,这就需求用到逆变了。

Kotlin 和 Java 的逆变Google

逆变其实是把承继关系倒置过来,比方 Integegoogle翻译rNumb源码精灵永久兑换码er 的子类型google翻译,可是 Integer 加逆变通配符之后,Number? super Integer 的子类,如下图所示数据结构教程第5版李春葆答案

Kotlin 和 Java 泛型的缺点和运用场景

  • 在 Java 顶用通配符 ? supegoogler T 表明逆变,其间 ? 表明不知道类型,super 主要用来束缚不知道类型的子类型 T,比方 ? super动画头像 Number,只需声明时传入是 Number 或许 Number 的父类型都数据结构c语言版第二版课后答案能够
  • 在 Kotlin 中关键字 in T 表明逆变,意义和 J数据结构题库ava 相同

现在咱们将上面的代码简单修正一下,在花三秒钟考虑一下是否能够正常编elementanimation译。

// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);

答案能够正常数据结构与算法编译,逆变通配符 ? super Number数据结构知识点总结 或许关键字 in 将承继关google商店系倒置过来源码编辑器下载,主要用来束缚不知道类型的子类型,在上面的比如中,编译器知道子类型是 Number,因而只需是 Number 的子类都能够数据结构增加。

逆变能够往调集源码编辑器下载中增加元素,源码编辑器下载那么能够获取元素数据结构c语言版吗?咱们花三秒钟时间考虑一下,下面的代码是否能够正常编译。

// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
numbers.get(0)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);
numbers.get(0);

不管调用 add() 办法仍是调用 get() 办法,都能够正常编译经过,现在将上面的代码修正一下,考虑一下是否能够正常编译经过。

// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
val item: Int = numbers.get(0)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);
int item = numbers.get(0);

调用 get() 办法会源码网站编译失利,由于 numbers.get(0) 获取的的值是 Object 的类型,因而它不能直接赋值给 int 类型,逆变和协变相同,放宽了对数据类型的束缚,可是价值是 不能依照泛型类型读取元素,也就是说往调集中增加 int 类型的数据,调用 get() 办法获取到的不是 igoogle服务框架nt 类型的数据。

对这一小节内容,咱们简单的总结一下。

关键字(Java/Kotli数据结构题库n)增加读取
协变 ? ext动画ends / out
逆变 ? super / in

Kotlin 和 Jav数据结构c语言版a 数组协变的不同之处

不管是 Kotlin 仍是 Java 它们协数据结构c语言版变和逆变的意义的都是相同的,只不过通配符不相同,可是他们也有不同之处。

Java 是支撑数组协变,代码如下所示:

Number[] numbers = new Integer[10];

可是 Java 中的数组协变有缺点,将上面的代码修正一下,如下所示。

Number[] numbers = new Integer[10];
numbers[0] = 1.0;

能够正常编译,可是运转的时分会溃散。

Kotlin 和 Java 泛型的缺点和运用场景

由于最开端我将 Number[] 协变成 Integer[],接着往数组里增加了 Double 类型的数据,所以运转会溃散。

而 Kotlin 的解决方案十分的干脆,不支撑数组协变,编译的时分就会犯错,关于数组逆变 Koltin 和 Java 都不支撑。

协变和逆变的运用场景

协变动画大放映和逆变运用的时分需求遵从 PECS(Producer-Extends, Consumer源码-Super)准则,即 ? extends 或许 out 作为生产者,? super 或许 in 作为顾客。遵从这个准则的好处是,能够在编译阶段确保代码安全,削减不知道过错的产生。

Kotlin 和 Java 泛型的缺点和运用场景

协变运用

  • 在 Java 顶用通配符 ? extends 表明协变
  • 在 Kotlin 中关键字 out 表明协变

协变只能读取数据,不能增加数据,所以只能作为生产者,向外供给数据,因数据结构c语言版第二版课后答案而只能用来输出,不必用来输入。

在 Koltin 中一个协变类动画制作软件,参数前面加上 outgoogle服务框架饰后,这个参数在google中国当前类中 只能作为google浏览器函数的回来值,或许润饰只读特点 ,代码如下所示。

// 正常编译
interface ProduceExtends<out T> {
    val num: T          // 用于只读特点
    fun getItem(): T    // 用于函数的回来值
}
// 编译失利
interface ProduceExtends<out T> {
    var num : T         // 用于可变特点
    fun addItem(t: T)   // 用于函数的参数 
}

当咱们确认某个目标只作为生产者时,向外供给数据,或许作为办法的回来值时,咱们能够运用 ? extends 或许 out

  • 以 Kotlin 为例,例如 Iterator#next() 办法,运用了关键字 out,回来调集中element是什么意思每一个元素

Kotlin 和 Java 泛型的缺点和运用场景

  • 以 Java 为例,例如 ArrayListgoogle浏览器#addAlgoogle浏览器l() 办法,运用了通数据结构严蔚敏配符 ? extendsgoogle

Kotlin 和 Java 泛型的缺点和运用场景

传入参数 Collection&l源码编辑器下载t;? extends E> c 作为生产者给 ArrayList 供给数据。

逆变运用

  • 在 Java 中运用通配符 ? su数据结构per 表明逆变
  • 在 Kotlin 中运用关键字 in 表明逆变

逆变只能增加数据,不能依照泛型读取数据,所以只能作为顾客,因而只能用来输入,不能用来输出。

在 Koltin 中一个逆变类,参数前面加上 in 润饰后,这个参数在当前类中 只能作为函数的参数,或许润饰可变特点

// 正常编译,用于函数的参数
interface ConsumerSupper<in T> {
    fun addItem(t: T)
}
// 编译失利,用于函数的回来值
interface ConsumerSupper<in T> {
    fun getItem(): T
}

当咱们确认某个目标只作为顾客,作为参数传入时,只用来增加数据,咱们运用通配符 ? super 或许关键字 in

  • 以 Kotl数据结构in数据结构有哪些 为例,例如扩展办法 Iterable#filterTo(),运用了关键字 in,在内部只用来增加数据

Kotlin 和 Java 泛型的缺点和运用场景

  • 以 Java 为例,例如 ArrayList#forEach() 办法,运用了通配符 ? super

Kotlin 和 Java 泛型的缺点和运用场景

不知道小伙伴们有没有留意到,在上面的源码中,别离运用了不同google谷歌搜索主页的泛型标记符 TE,其googleplay实咱们略微留意一下,在源码中有几个高频的泛型标记符 TEKV 等等,它们别离运用在不同的场景。

标记符运用场景
T(Type)
E(Element)调集
K(Key)
V(Value)

全文数据结构实验报告到这里就完毕了,动画制作软件感谢你的阅览,坚持原创不易,欢迎在看、点赞、google网站登录入口共享给身边的小伙伴,我会继续共源码网站享原创干货!!!

真诚引荐你关注我,大众号源码交易平台:ByteCode ,继续共享硬核原创内容,Kotlinelementary、Jetpack、功能优化、体系源码、算法及数据数据结构结构、动画、大厂面经。



近期必读抢手文章

  • CPU 如何记录函数调用进程和回来进程
  • 揭秘数据结构题库反射真的很耗时吗,射 10 万次耗时多久
  • 你知道 Iterabgoogle网站登录入口le 有多慢吗?试试它提数据结构c语言版严蔚敏第二版答案升功能
  • 揭秘 Kotlin 1.6.2源码0 重磅功能 Context Receivers
  • Stack Overflow 上最抢手的 10 个 Kotlin 问题
  • Android 12 已来,你的 App 溃散了吗?
  • Google 宣布废弃 LiveDgoogle浏览器ata.observe 办法
  • 影响功能的 Kotlin 代码(一)
  • 揭秘 Kotlin 中的 == 和 ===

最后引荐长期更新和维护的项目

  • 个人博客,将数据结构c语言版一切文章进行分类,欢迎源码时代前去检查 hi-dhl.com

  • KtKit 细巧而实用,用 Kotlin动画片少儿小猪佩奇 言语编写的工具库,欢迎前去检查 KtKit

  • 方案树立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理剖析文章,正在逐渐增加 Jetpack 新成员,仓库继续源码更新,欢迎前去检查 AndroidX-Jetpack-Practice

  • LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程题解,言源码语 Java 和 kotlin,包含多种解法、解题思路、时间复杂度、空间复杂度剖析

Kotlin 和 Java 泛型的缺点和运用场景

  • 剑指 offer 及国内外大厂面试题解:在线阅览
  • LeetCode 系googleplay列题解:在线阅览

发表评论

提供最优质的资源集合

立即查看 了解详情