重新审视 Kotlin 反射,我觉得可以合理使用

2020-02-20 13:39:57 浏览数 (1)

我之前每次跟别人分享 Kotlin 反射的时候,都会让大家小心点儿它,因为它一方面体积大,另一方面性能也差,不仅如此,还有一些小毛病,这些内容在我很久之前的一篇文章详细讨论了:Kotlin 反射你敢用吗?。那么时过境迁,今天的 Kotlin 反射怎么样了?

1. 不支持的 built-in Kotlin types

这个问题我们用当时的版本很容易复现,只需要运行下面的代码即可:

代码语言:javascript复制
String::class.memberFunctions

但是,它在 1.2.60 已经修复了。也就是说,如果你使用 Kotlin 反射,请立刻马上更新到 1.2.60 以上的版本,这样就不会有 built-in types 的问题。

我们再简单唠叨几句,这个问题其实涉及到的都是 Kotlin 与 Java 存在映射关系的类,例如 String、枚举、Map 等等。

2. 运行性能差

Kotlin 反射耗时确实比 Java 反射耗时长,毕竟一方面没有 Java 虚拟机加成,Kotlin 的反射主要依赖于 @MetaData 注解,可参考:Kotlin 反射与 MetaData 的关系在混淆后浮出水面! 和 认识下 Kotlin 反射背后的男人:@Metadata,另一方面 Kotlin 反射提供的能力也比 Java 反射多很多(这主要与 Kotlin 本身的语法特性多是相对应的),所以付出多少得到多少,只要它的慢在合理范围内,我们其实也是可以接受的。

2.1 首次运行慢

涉及到注解解析和加载的问题,第一次运行必然慢,我用 1.3.0-rc-146 简单测试了一下:

单位:μs

构造对象

访问属性

修改属性

调用方法

Java 反射

2888.1

347.9

70.8

78.8

Kotlin 反射

1440742.1

61179.5

3496.7

199.3

第一次访问 Kotlin 反射确实要慢很多。

2.2 后续运行约为 Java 反射的 1.5~2 倍

后续运行由于是直接访问内存,因此性能上不会有数量级的差别:

单位:μs

构造对象

访问属性

修改属性

调用方法

Java 反射

15.5

16.8

11.0

26.3

Kotlin 反射

20.2

38.6

48.4

33.5

尽管仍然比 Java 反射耗时多一些,但对于使用反射的场景来说,这样通常也是可以接受的。

需要注意的是,过去的版本应该在后续的执行中也不会很慢,只是去年的文章我没有太注意这部分数据。

3. 2.5M的 Jar 包

当时提到了 2.5M 的 jar 包的问题,如果你是在 Server 端使用 Kotlin 反射,相信你也不会 care 这点儿包体积,更何况编译完之后也只有 400K 的样子,这对于 Android 应用来说也不是什么大问题,毕竟 Apk 的瘦身大头应该在资源上,也许你把设计出的某一个序列帧动画用代码实现了就可以省掉好几 MB。

4. 小结

其实之前让我觉得不安的主要是性能问题,显然这样看来倒也还好。而一些未完善的部分也在最近的版本得到了完善,因此 Kotlin 反射库的使用评级由“谨慎使用”上调为“合理使用”。


0 人点赞