前几期总有人说太简单,哼,今天的话题能难倒一大批大公司的。我们做分享不是为了证明自己牛逼,而是为了帮助大家。不讲基础只讲高级,那起点低的人就不配学习呗?
大家好,我是扔物线朱凯。码上开学的 Kotlin 基础部分在上期已经完结,这期是高级部分的第 1 期:Kotlin 的泛型。不过这次在上视频之前,我想请大家帮我个忙:
在上次的文章里,我提到:
在码上开学项目发布之后,我收到了哔哩哔哩的通知,告诉我拿到了哔哩哔哩「新秀奖」的参选权。我决定参选。所以在这里,我请各位一直关注 HenCoder、关注扔物线、关注码上开学的同学们,如果你喜欢我的内容,认同我做的事:请在接下来的一个月内里,多多去 B 站看我的视频(B 站搜索「扔物线」就能找到我)。
另外如果你喜欢我的视频,别忘了在 B 站的每个视频下面点击关注、收藏留言和分享。但一定记得,前提是你喜欢我的视频!在此先谢谢啦!
扔物线,公众号:HenCoder扔物线第一次公开演讲 Kotlin 的协程,就在这周六
也就是说,从这期开始,我的每期视频都会参加哔哩哔哩的新秀奖大赛。所以如果可以的话,今天这个视频,以及现在开始的三周内的视频,请尽量去哔哩哔哩看(视频内容一样的),助我参赛。
传送门:
看完如果喜欢,别忘了点赞投币收藏素质三连!
那如果你对哔哩哔哩毫无兴趣,就忽略上面的,往下继续看吧:
看完视频还不过瘾?
可以点击下方「阅读原文」或者用浏览器打开 kaixue.io/kotlin-generics ,把和视频配套的文章看了。
文章部分内容预览:
这期是码上开学 Kotlin 系列的独立技术点部分的第一期,我们来聊一聊泛型。
提到 Kotlin 的泛型,通常离不开
in
和out
关键字,但泛型这门武功需要些基本功才能修炼,否则容易走火入魔,待笔者慢慢道来。下面这段 Java 代码在日常开发中应该很常见了:
☕️List<TextView> textViews = new ArrayList<TextView>();
其中
List<TextView>
表示这是一个泛型类型为TextView
的List
。那到底什么是泛型呢?我们先来讲讲泛型的由来。
现在的程序开发大都是面向对象的,平时会用到各种类型的对象,一组对象通常需要用集合来存储它们,因而就有了一些集合类,比如
List
、Map
等。这些集合类里面都是装的具体类型的对象,如果每个类型都去实现诸如
TextViewList
、ActivityList
这样的具体的类型,显然是不可能的。因此就诞生了「泛型」,它的意思是把具体的类型泛化,编码的时候用符号来指代类型,在使用的时候,再确定它的类型。
前面那个例子,
List<TextView>
就是泛型类型声明。既然泛型是跟类型相关的,那么是不是也能适用类型的多态呢?
先看一个常见的使用场景:
☕️TextView textView = new Button(context);// ???? 这是多态List<Button> buttons = new ArrayList<Button>();List<TextView> textViews = buttons;// ???? 多态用在这里会报错 incompatible types: List<Button> cannot be converted to List<TextView>
我们知道
Button
是继承自TextView
的,根据 Java 多态的特性,第一处赋值是正确的。但是到了
List<TextView>
的时候 IDE 就报错了,这是因为 Java 的泛型本身具有「不可变性 Invariance」,Java 里面认为List<TextView>
和List<Button>
类型并不一致,也就是说,子类的泛型(List<Button>
)不属于泛型(List<TextView>
)的子类。Java 的泛型类型会在编译时发生类型擦除,为了保证类型安全,不允许这样赋值。至于什么是类型擦除,这里就不展开了。
你可以试一下,在 Java 里用数组做类似的事情,是不会报错的,这是因为数组并没有在编译时擦除类型:
☕️TextView[] textViews = new TextView[10];
但是在实际使用中,我们的确会有这种类似的需求,需要实现上面这种赋值。
Java 提供了「泛型通配符」
? extends
和? super
来解决这个问题。Java 中的
? extends
在 Java 里面是这么解决的:
☕️List<Button> buttons = new ArrayList<Button>(); ????List<? extends TextView> textViews = buttons;
这个
? extends
叫做「上界通配符」,可以使 Java 泛型具有「协变性 Covariance」,协变就是允许上面的赋值是合法的。在继承关系树中,子类继承自父类,可以认为父类在上,子类在下。
extends
限制了泛型类型的父类型,所以叫上界。它有两层意思:
完整文章可以点击下方「阅读原文」或者用浏览器打开 kaixue.io/kotlin-generics 查看。
这是什么项目?
码上开学,是一个针对 Android 工程师的 Kotlin 上手指南。虽然针对上手,但包含了许多你在网上任何地方(包括英文社区、包括官方文档)都看不到的必备的技术细节。
码上开学项目由扔物线创办,目前由即刻 Android 团队协作一同产出。
觉得赞?关注吧!
如果你觉得赞,就分享、转发和点击右下角的在看,让更多需要的人也看到吧。但前提一定是,你真的觉得赞。
最后,别忘了扫码关注,我们的后续内容将第一时间推送到你。