优化@BuilderInference注解,Kotlin高版本下了这些“毒手”!

4,101 阅读4分钟

大家好,之前项目准备升级到kotlin插件最新版本,所以对于kotlin1.5.0及以上特性进行了一番了解,发现kotlin官方为了提高部分注解的使用体验,做了不少的优化工作,这里就带大家了解下这些注解,希望能帮助你进一步提升对Kotlin的认知。

一. @BuilderInference注解基本认知

这个注解大家可能有些陌生,但在日常开发中肯定使用过用其实现的扩展函数,比如buildList{}构建集合:

我们一般这样使用:

可以看到buildList{}使用时不用显示指定方法泛型类型就完成了自动推断,靠的就是@BuilderInference注解,接下来我们具体的讲一讲。

二. @BuilderInference注解基本使用

我们先看一段官方源码解释:

简单来说,这个注解就是帮助编译器从方法函数类型的参数调用中推断真正的泛型类型,这句话说起来比较绕,比如下面这个例子:

class BuildAction<T> {
    var sth : T? = null

    fun action(t: T){
        sth = t
    }
}

fun <T> test100(@BuilderInference block: BuildAction<T>.() -> Unit): T? {
    val sth = BuildAction<T>()
    sth.block()
    return sth.sth
}

当我们使用test100()方法时,可以不需要传递具体的泛型类型,而是编译器直接从函数类型参数block的接收者BuildAction方法的调用中直接推断该类型

可以看到,上面的截图中不显示指定泛型类型就推断出了test100()方法的泛型为StringbuildList{}构建集合同样是这个原理,可以说@BuilderInference注解非常的好用。

但是该注解在1.5.30及以下有个限制

也就是说,在方法函数类型block中:你只能通过调用方法显示传入对应的泛型类型参数才能推断方法类型,而无法通过调用的方法的返回值来推断函数类型,说起来还是绕口,我们直接举个例子,先给上面的BuildAction类直接增加一个返回值为泛型类型的方法:

class BuildAction<T> {
    //...
    fun obtain(): T {
        return sth!!
    }
}

然后我们继续调用下test100()方法:

直接就进行报错了,即无法通过调用方法并显示声明方法的返回值来推断test100函数的泛型类型,这对我们日常的使用还是不太方便的。

最终kotlin1.5.30出手了

三. kotlin1.5.30增强@BuilderInference注解功能

只需要增加一个compile option:-Xunrestricted-builder-inference, 或者在kotlinOption中增加一个配置字段: -language-version 1.6,都能解除上面的限制,这里我们使用第一种:

  1. 首先在build.gradle脚本中增加下面的配置:

  1. 继续测试下上面的代码看下还会不会报错;

可以看到不报错了,并且正确推断出了test100方法的泛型类型为String

经过这么一波优化,@BuilderInference注解更加强大、更加方便了,但是大家不觉得推断方法泛型类型为啥每次都要写这么一个注解,多麻烦,编译器就不能自动帮助我们这种识别使用场景并进行方法泛型类型推断吗?

kotlin1.6.0出手了,下面我们讲讲这个版本做了啥优化。

四. kotlin1.6.0去除@BuilderInference显示声明

先上一波官方截图:

这段话我们需要关注的有两点:

  1. 当项目kotlin插件升级到1.6.0及以上版本,推断函数泛型类型(即上面讲解的通过函数类型内的方法返回值类型推断)不用增加-Xunrestricted-builder-inference这个compiler option,编译器默认启动该特性;
  2. 新增-Xenable-builder-inference这个compiler option,以后根据方法函数类型参数推断方法泛型类型就不用再增加@BuilderInference注解了

接下来我们稍微改造下上面的例子测试下:

  1. 调整build.gradle中compiler option配置:

  1. 改造下上面的test100()方法,去除@BuilderInference注解:

  1. 调用test100()测试:

没有进行任何的报错,完美解决了@BuilderInference注解需要显示声明的问题。

五. 总结

经过上面的讲解,核心点主要如下:

  1. 1.5.30及以下通过-Xunrestricted-builder-inference这个compiler option增强@BuilderInference注解功能,实现通过方法函数类型参数中内部所调用的方法返回值类型来推断方法泛型类型;

  2. 1.6.0及以上,默认实现-Xunrestricted-builder-inference对应增强的功能,无需显示声明这个compiler option,并且通过声明-Xenable-builder-inference这个compiler option,不用再显示声明@BuilderInference注解了;

谢谢大家观看。


本文正在参加「金石计划」