我在Kotlin中理解const val
用于声明常量,val
用于只读属性。但是,我想知道以下情况,哪一个更适合使用。
假设我有一个片段,需要一个密钥才能用于saveInstanceState
和restoreInstanceState
。我想知道以下两个选项中哪一个更好:
class MyFragment {
private val MY_KEY = "my_key"
...
}
private const val MY_KEY = "my_key" // declared in the same file.
class MyFragment {
...
}
我更喜欢#option 2,因为它清楚地表明MY_KEY
是一个常量,并且值是在编译时确定的。但是,由于它在顶层声明,因此需要在编译的java代码中创建一个类MyFragmentKt
(假设文件名为MyFragment.kt
)。在#option 1中,没有生成额外的类,虽然MY_KEY
的值将在运行时分配而不是常量,但这在特定情况下的使用方式没有区别
所以虽然我个人更喜欢#option 2,但我的分析让我觉得#option 1并不差,如果不是更好的话。我只是想知道其他开发者如何看待这个问题,以及#option 2是否有任何其他好处,我还没有想到。感谢。
答案 0 :(得分:16)
每次编写(非内联)lambda表达式时,都创建了另一个类。与此相比,创建一个用于保存顶级声明的类似乎很小。
此外,如果您在顶层的所有内容都是一个常量声明,它将被内联到每个使用站点(按规范),因此拥有类本身将变为未引用,因此可以通过ProGuard的最小化来定位。它很可能不会出现在您的制作APK中。
答案 1 :(得分:10)
这两个选项之间不仅存在语义差异。
选项1(类内val
)是一个实例字段。
选项2(顶级const val
)是顶级"静态"成员(大致,因为static
在Kotlin中不存在。)
这就是生成MyFragmentKt
类的原因:顶级成员被编译为名为[Filename]Kt
的类。
我会考虑第三种选择:
class MyFragment {
companion object {
private const val MY_KEY = "my_key"
}
}
这样,MY_KEY
(来自Java)是static
类的MyFragment
成员,因为JvmStatic
是const
变量的推断。将生成Companion
类(但它将为空)。
由于您的原始方法是课程中的一个字段,我觉得companion object
/ static
常量可能更合适。
答案 2 :(得分:-2)
我认为选项#2是正确的方式。