【发布时间】:2016-11-05 19:12:47
【问题描述】:
是否有充分的理由(在性能方面)替换 a:
val SOME_CONST = "value"
与
companion object {
val SOME_CONST = "value"
}
添加@JvmStatic 注释会改变结果吗?
【问题讨论】:
-
你可以为常量使用一个独立的对象,不一定是伴侣;)
标签: kotlin
是否有充分的理由(在性能方面)替换 a:
val SOME_CONST = "value"
与
companion object {
val SOME_CONST = "value"
}
添加@JvmStatic 注释会改变结果吗?
【问题讨论】:
标签: kotlin
是的,val 存储在 companion object 中更有效。您可以使用Kotlin bytecode viewer 找出这些选项被编译成什么。
以下是我注意到的可能会影响性能的事情:
伴随对象val只存储一次,不像实例val,它实际上存储在每个实例中,从而增加了实例的内存占用(String字面量is stored in constant pool,但一个实例会有一个对它的引用) 和实例创建时间(在构建过程中,必须填写一个字段)。
在不同的情况下,连续多次访问伴随对象val 比使用val 更适用于CPU 缓存:它具有更好的locality of reference。取消引用不同的实例以访问其中的val 可能会导致 CPU 缓存未命中,这对性能不利。
但是,如果 val 仅在同一类的实例方法中使用,所描述的效果几乎不会影响性能,因为无论如何这些方法可能会取消引用 this,而且这可能会更好,不会导致可能的缓存访问伴随对象时错过。
添加@JvmStatic 会使访问速度更快一些。没有它,访问该值需要获取静态 Companion 引用并在其上调用 getSOME_CONST()。有了@JvmStatic,就会有静态方法getSOME_CONST()(跳过Companion)。还有@JvmField,它创建了一个可以直接访问的公共字段,甚至不需要调用getter。
但 JIT 编译器可能会优化前两种情况的 getter 访问,因此注释的效果几乎不会被注意到。
此外,除了性能之外,实例 val 具有值的语义,每个实例可能不同,因此 companion object 似乎更适合全局常量值的情况。
【讨论】: