今日写这篇文章主要是有两个原因:
-
不是为了卷,仅仅为了希望能在明日过年前升到5级,拿个
优秀创作者
的称谓,提早祝大家新年快乐; -
最近项目kotlin插件升级到了1.6.21,咬着牙把官方英文文档看了下,发现一些有用的常识共享给大家;
本篇文章主要是介绍下1.6.20供给了的一个新特性-Xjvm-default=all
和调配使用的@JvmDefaultWithCompatibility
注解:
不过在讲解这个之前,咱们需求一些准备常识。
前置常识-Kotlin接口默许办法完结机制
大家应该都知道Kotlin接口的办法是能够默许完结的:
interface ICallback {
fun execute() {
println("execute...")
}
}
看着确实是对接口办法完结了默许重写,但真的是表面上这样的吗?子类真的不需求完结办法了吗?
下面咱们简单证明下:搞一个java类完结这个接口,不重写任何办法,看看会不会报错:
很明显报错了,提示咱们子类需求重写接口的execute()
办法,所以咱们能够得出一个定论:Kotlin接口的办法的默许完结是伪完结
。
那kotlin的这个伪完结的完结原理是啥呢,这儿咱们反编译下java代码看一看:
很明显的看到,ICallback
接口的办法仍是个笼统办法,并没有默许完结(这便是为什么java直接完结这个接口会报错的原因)。其次还生成了一个DefaultImpls
中心类,这个中心类供给了真实默许完结的execute()
办法逻辑。
当咱们kotlin子类完结这个接口时:
class ICallbackChild2 : ICallback
这样写并不会产生任何报错,咱们反编译成java代码看下:
能够看到,编译器会默许协助咱们完结接口的execute()
办法,并调用了DefaultImpls
类中的execute()
完结了默许完结。
以上便是kotlin接口办法默许完结的原理,真实的完结逻辑经过一个默许生成的DefaultImpls
类去完结。
现在咱们考虑下,为什么kotlin要这么完结呢,直接凭借java的default
关键字不能够吗,上面这种完结还多了一个类的开支?
Kotlin官方当然也发现了这个问题,所以在kotlin1.6.20供给了-Xjvm-default=all
这个compile option来进行优化,接下来听我逐个介绍。
-Xjvm-default=all
上台
想要使用这个,需求在Android Studio中build.gradle添加下面装备:
kotlinOptions {
jvmTarget = '1.8'
freeCompilerArgs += "-Xjvm-default=all"
}
这个完结之后,咱们仍是拿上面的接口作为比如讲解:
interface ICallback {
fun execute() {
println("execute...")
}
}
咱们再次反编译成java代码看下:
能够看到,凭借了default
关键字完结了接口办法的默许完结,而且没有生成上面的DefaultImpls
中心类,算是一个很不错的优化。
如果咱们项目中之前界说了许多的kotlin接口默许办法完结,那这个编译优化能够协助你削减许多中心类的生成。
这儿咱们再次考虑一下,咱们忽然添加了这个compile option消除了DefaultImpls
类,但是假设之前的代码有使用到这个类怎么办呢?咱们不太或许挨个每个地方的去调整本来的事务代码,这样工作量就非常大了。
所以kotlin官方交心的供给了@JvmDefaultWithCompatibility
注解做了一个兼容处理,接下来听我逐个介绍。
@JvmDefaultWithCompatibility
做个兼容
先上一张官方图,最需求注意的便是第一行和最后一行:
在咱们添加了上面的-Xjvm-default=all
之后,凭借default
消除了DefaultImpls
这个协助类后,咱们还能够经过@JvmDefaultWithCompatibility
这个注解指定哪个接口保留这个DefaultImpls
类,由于其他地方或许需求显现调用这个类。
这儿咱们仍是以上面的ICallback
接口为例:
@JvmDefaultWithCompatibility
interface ICallback {
fun execute() {
println("execute...")
}
}
咱们反编译成java代码看下:
能够看到,使用default
完结了默许办法,而且DefaultImpls
类依然存在,这就对过去kotlin接口的办法默许完结保持了兼容,尽量避免对事务逻辑的影响。
总结
其实kotlin之前有供给-Xjvm-default=all-compatibility
和注解@JvmDefaultWithoutCompatibility
调配,不过这样关于事务开发不太友爱,比如新增接口容易漏掉注解添加,再比如或许会对事务逻辑非public部分代码侵略过深等。
所以这儿官方又供给了-Xjvm-default=all
和@JvmDefaultCompatibility
调配使用。希望本篇文章对你有所协助。
新年快乐