Kotlin1.8新增特性,进来了解一下
大家好,之前我已经写过了分析kotlin1.5、1.6、1.7、1.9插件版本新增的一些特性,唯独kotlin1.8的特性还没好好讲讲,本篇文章就带大家好好分析下kotlin1.8新增了那些特性,能对我们日常开发带来哪些帮助。
其中Kotlin1.8.0提供的特性有限,本篇文章主要是分析Kotlin1.8.20提供的一些新特性。下面是支持该插件的IDE对应版本:
一. 提供性能更好的Enum.entries
替代Enum.values()
在之前,如果我们想遍历枚举内部元素,我们通常会写出以下代码:
enum class Color(val colorName: String, val rgb: String) {
RED("Red", "#FF0000"),
ORANGE("Orange", "#FF7F00"),
YELLOW("Yellow", "#FFFF00")
}
fun main() {
Color.values().forEach {
println("${it.rgb}--${it.colorName}--${it.name}")
}
}
但是不知道大家是否清楚,Color.values()
其实存在性能问题,换句话说,每调用一次该方法,就会触发重新分配一块内存,如果调用的频率过高,就很可能引发内存抖动。
我们可以反编译下枚举类简单看下原因:
Color.values()
每次都会调用Object.clone()
方法重新创建一个新的数组,这就是上面说的潜在的性能问题,github上也有相关的问题链接,感兴趣的可以看下:HttpStatus.resolve allocates HttpStatus.values() once per invocation。
同时Color.values()
返回的是一个数组,而在我们大多开发场景中,可能集合使用的频率更高,这就可能涉及到一个数组转集合的操作。
基于以上考虑,Kotlin1.8.20官方提供了一个新的属性:Color.entries
,这个方法会预分配一块内存并返回一个不可变集合,多次调用也不会产生潜在的性能问题。
我们简单看下使用:
fun main() {
Color.entries.forEach {
println("${it.rgb}--${it.colorName}--${it.name}")
}
}
输出:
同时我们也可以从反编译的代码中看出区别:
不会每次调用都重新分配一块内存并返回。
如果想要使用这个特性,可以加上下面配置:
compileKotlin.kotlinOptions {
languageVersion = "1.9"
}
另外多说一下,IntelliJ IDEA 2023.1版本也会检测代码中是否存在Enum.values()
的使用,存在就提示使用Enum.entries
代替。
二. 允许内联类声明次级构造函数
内联类在Kotlin1.8.20之前是不允许带body的次级构造函数存在的,也就是说下面的代码运行会报错:
@JvmInline
value class Person( val fullName: String) {
constructor(name: String, lastName: String) : this("$name $lastName") {
check(lastName.isNotBlank()) {
"Last name shouldn't be empty"
}
}
}
fun main() {
println(Person("a", "b").fullName)
}
运行看下结果:
如果没有次级构造函数body,下面这样写是没问题的:
constructor(name: String, lastName: String) : this("$name $lastName")
如果想要支持带body的次级构造函数,只需要在kotlin1.8.20插件版本上和上一个特性一样增加languageVersion = "1.9"
配置即可。
然后上面的代码块运行就没问题了,我们看下输出:
fun main() {
println(Person("a", "").fullName)
}
准确的执行了次级构造函数body内的逻辑。
三. 支持java synthethic属性引用
这个特性用文字不好解释,我们直接通过代码去学习下该特性。
当前存在一个类Person1
:
public class Person1 {
private String name;
private int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
在Kotlin1.8.20之前,以下这种写法是会报错的:
而是必须改成sortedBy(Person1::getAge)
才能运行通过。
和上面特性一样,如果想要支持Person1::age
这种引用方式,只需要在kotlin1.8.20插件版本上和上一个特性一样增加languageVersion = "2.1"
配置即可。
PS:请注意,Kotlin官方网站提示配置
languageVersion = "1.9"
就能使用上面的实验特性,但是编译器还是提示报错,然后你找报错提示信息改成了languageVersion = "2.1"
就正常了。
四. 新Kotlin K2编译器的更新
就是说目前Kotlin K2编译器还是一个实验阶段,不过Kotlin官方在其stable的路上又增加了一些更新:
- 序列化插件的预览版本;
- JS IR编译器的alpha支持;
- Kotlin2.0版本特性的引入;
如果大家想要体验下最新版的Kotlin K2编译器,增加配置:languageVersion ="2.0"
即可。
五. Kotlin标准库支持AutoCloseable
这个AutoCloseable
接口就是用来支持资源关闭的,搭配提供的use
扩展函数,就能帮助我们在资源流使用完毕后自动关闭。
Kotlin之所以在标准库中支持,应该是想要支持多平台吧。
六. Kotlin标准库支持Base64编解码
这里不做太多介绍,看下面的使用例子即可:
七. Kotlin标准库@Volatile支持Kotlin/Native
@Volatile注解在Kotlin/JVM就是保证线程之间可见性以及有序性的,kotlin官方在Kotlin/Native中也支持了该注解使用,有兴趣的可以实战试下效果。
总结
本篇文章主要是介绍了Kotlin1.8版本新增的一些特性,主要挑了一些我能理解的、常用的一些特性拉出来介绍,希望能对你有所帮助。
历史文章
kotlin密封sealed class/interface的迭代之旅
优化@BuilderInference注解,Kotlin高版本下了这些“毒手”!
@JvmDefaultWithCompatibility优化小技巧