两个Kotlin优化小技巧,你绝对用的上
大家好,本篇文章仍然聊聊kotlin官方做的一些优化工作,主要包括以下三个方面:
- 数据对象
data object
的支持 @Repeatable
注解的优化
接下来就带大家介绍下上面三个特性。
一. 数据对象data object
的支持
该特性由kotlin1.7.20插件版本提供,并处于实验阶段。
这个特性主要是和原来的object
声明的单例类的toString()
方法输出有关,在了解这个特性之前,我们先看下下面一个例子:
object Single1
fun main() {
println(Single1)
}
输出:
这个输出本质上就是一个类名、@、地址的拼接,有时候你想要打印输出的仅仅是类名,就得需要重写下toString()
方法:
object Single1 {
override fun toString(): String {
return "Single1"
}
}
然后再看一个密封类的例子:
sealed interface Response {
data class Success(val response: String): Response
data class Fail(val error: String): Response
object Loading : Response
}
fun main() {
println(Response.Success("{code: 200}"))
println(Response.Fail("no net"))
println(Response.Loading)
}
输出:
可以看到,大家都是密封子类,但就这个Loading
类的输出比较"丑陋",没有上面两个兄弟类的输出简洁清爽。
接下来我们就要介绍下主人公数据对象data object
了,这个东西其实使用起来和object
一模一样,核心的区别就是前者的toString()
更加简洁。
接下来从一个例子一探究竟:
data object Single2
fun main() {
println(Single2)
}
看下输出:
输出是不是比上面的object Single1
更加简单明了。最重要的是在密封类中使用效果更加,我们把上面密封类Loading
声明为data object
:
data object Loading : Response
看下最终的输出结果:
这下子输出结果是不是清爽更多!!
讲完了应用,我们再java的角度看下其背后的实现机制,相比较于object
,data object
会多了下面这三个重写方法:
public final class Single2 {
@NotNull
public String toString() {
return "Single2";
}
public int hashCode() {
return -535782198;
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (!(var1 instanceof Single2)) {
return false;
}
Single2 var2 = (Single2)var1;
}
return true;
}
}
我们需要关心的toString()
方法就是直接重写返回了当前的类名。
如果想要使用这个特性,我们只需要增加如下配置即可:
compileKotlin.kotlinOptions {
languageVersion = "1.9"
}
二. @Repeatable
注解优化
该特性由kotlin1.6.0插件版本提供优化。
在了解这个特性之前,我们先回忆下@Repeatable
这个注解在java中的使用:
如果一个注解在某个方法、类等等上面需要重复使用,那就需要@Repeatable
帮助。
- 首先定义需要重复使用的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Fruits.class)
public @interface Fruit {
String name();
String color();
}
- 然后定义注解容器,用来指定可重复使用的注解类型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Fruits {
Fruit[] value();
}
然后就可以在代码中这样使用:
@Fruits({
@Fruit(name = "apple", color = "red"),
@Fruit(name = "origin", color = "yellow"),
})
public class Detail {
}
大家有没有发现,可重复注解定义起来还是由一丢丢的麻烦,接下来轮到我们kotlin重磅出击了。先看下面一个例子:
@Repeatable
annotation class Animal(val name: String)
在kotlin中我们只要声明一个需要重复使用的注解即可,kotlin编译器会自动帮助我们生成注解容器@Animal.Container
,然后我们就能在代码中这样使用:
@Animal(name = "dog")
@Animal(name = "horse")
public class Detail {
}
是不是非常简单便捷了。
如果你偏要显示指明一个包含注解,也可以,通过以下方式即可实现:
@JvmRepeatable(Animals::class)
annotation class Animal(val name: String)
annotation class Animals(val value: Array)
然后除了上面的使用方式,你在kotlin中还可以这样使用:
@Animals([Animal(name = "dog"), Animal(name = "dog")])
class Detail {
}
请注意:
- 如果非要显示声明一个注解容器,其属性的名称一定要为
value
; - 其次,注解容器和可重复性直接不能同时声明在同一个元素上;
另外,其实这个特性kotlin早就支持了,只不过kotlin1.6.0插件版本之前,kotlin这个特性只只支持RetentionPolicy.SOURCE生命周期的注解,并且还和java的可重复注解不兼容。
总结
这两个小技巧相信在大家日常开发中还是比较实用的,希望本篇能对你有所帮助。
参考文章:
Improved string representations for singletons and sealed class hierarchies with data objects
Repeatable annotations with runtime retention for 1.8 JVM target
来源:juejin.cn/post/7248249730478784569