首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Kotlin第七讲-泛型在Java和Kotlin上的差异

阅读本文前,如果对Java泛型不够了解,不妨先阅读我之前写的两篇说Java泛型的文章

语法比较

泛型方法

Java

Kotlin

查看Kotlin里的Comparable类和List类源码,Comparable类定义,List类定义,所以可以不必重复表明Comparable的逆变能力和List的协变能力。

不管是泛型类还是泛型方法,泛型的使用分为两个步骤

第一步,声明泛型参数

第二步,才是使用泛型参数

上面的泛型方法,以Java泛型方法为例,泛型声明部分是:

引入泛型类型名称为T,这个数据类型的关系是实现Comparable的类。

使用泛型的部分如下:

入参的集合具有对类型T的协变能力。

所以,有些书或者网上资料,会出现两个概念:声明点变型,使用点变型。这个概念说的就是这件事

再来看下in位置,和out位置的概念

所以,类型参数T上的关键字out有两方面含义:

具有协变的能力

T只能用在out位置

我们再看一个有趣的例子

我有一个方法,入参的一个集合,我希望入参集合元素是EditText的子类的集合,如何构建满足这个关系的方法呢?至少有下面的两种方式:

上面test2, test3方法都能实现预期的效果。不同的是,test2使用协变来实现,也意味着只能读不能写操作,test2不是泛型方法。test3方法通过在声明表明泛型参数的类型关系来实现,可读可写,它是泛型方法。

对应的Java代码如下

实现泛型参数多约束

Java

kotlin

这是Java语法上很大的不同,Kotlin要实现多约束,使用到where关键词,这是全新的表示法。

实化类型参数

来看一段Java代码:

入参是泛型的,通过instanceof来判断泛型具体是哪个类型。再看一段代码

泛型作为参数类型时,编译不通过。如果要完成上述的逻辑,要怎么实现?可以通过class近似等效实现

调用

Kotlin在语言层面作出了支持,对上述Java代码test2方法,kotlin代码如下:

因此需要具备两个条件:

是内联函数 inline

关键词 reified

集合协变

在Kotlin里,非空类型是可空类型的子类型。

Java实现的协变

Kotlin实现的协变

集合逆变

Java实现的逆变

对应的Kotlin逆变的实现:

变型(协变和逆变)涉及到集合元素,集合类。协变讲的是两个集合的元素是子类关系,这两个集合也是子类关系,有了子类关系,就可以用多态表示。逆变的关系是反过来的,逆变说得是,两个集合的元素是父类关系,这两个集合却能成为子类关系。

由此可见,在泛型里,extends 不全等于 :。extends代表子类型关系和协变,而Kotlin的 :只代表子类型关系。

星投影和Java无限制通配符?差异

星投影如何使用

投影一词,顾名思义,是对Any?的投影,获得了Any?部分的能力---Any?协变的能力,即失去写操作,只能读操作。

场景二:泛型类存储

所有不安全的逻辑都被隐藏在类的主体中,通过把这些逻辑局部化到一个分开的位置,预防了误用,保证了它不会被错误地使用。

其他

非空性与泛型

Java和Kotlin默认,泛型参数都是可空的,以Kotlin为例

泛型参数是可空类型,可以理解为默认实现,因此要实现非空类型,只需,如下

所以,泛型和是有区别的,前者是可空类型,后者是非空类型,确切说,和

小结

Kotlin和Java的差异,体现在语法和功能两个方面

语法上

Kotlin使用:替代 extends;

用星投影 * 替代?

用in, out来体现协变和逆变;

泛型类型多约束条件,Kotlin使用where关键词,而不用Java里&表示

功能上: 1. 新增了实化参数类型

参考资料

仔细说说Java中的泛型

Java 泛型 中 super 怎么 理解?与 extends 有何不同?

Java 泛型进阶

Java为什么要添加运行时获取泛型的方法

Kotlin实战

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180716G1BPH000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券