简体   繁体   English

Kotlin:const val vs val

[英]Kotlin: const val vs val

I understand in Kotlin const val is used to declare constants and val is for readonly properties. 我理解在Kotlin中const val用于声明常量, val用于readonly属性。 However, I'm wondering in the following case, which one is more suitable to use. 但是,我想知道以下情况,哪一个更适合使用。

Assume I have a fragment which needs a key to use for saveInstanceState and restoreInstanceState . 假设我有一个片段需要一个密钥用于saveInstanceStaterestoreInstanceState I'm wondering which one of the following 2 options is better: 我想知道以下两个选项中哪一个更好:

Option 1: 选项1:

class MyFragment {
    private val MY_KEY = "my_key"
    ...
}

Option 2: 选项2:

private const val MY_KEY = "my_key" // declared in the same file.

class MyFragment {
    ...
}

I'd prefer the #option 2 since it makes it clear that MY_KEY is a constant and the value is determined in compile time. 我更喜欢#option 2,因为它清楚地表明MY_KEY是一个常量,并且值是在编译时确定的。 However since it's declared on the top level, it costs a class ie MyFragmentKt (assume the file name is MyFragment.kt ) to be created in the compiled java code. 但是,由于它是在顶层声明的,因此需要在编译的java代码中创建一个类,即MyFragmentKt (假设文件名是MyFragment.kt )。 In #option 1, no extra class is generated and although MY_KEY 's value is going to be assigned at runtime and not constant, that makes no difference in how it's used in this specific case. 在#option 1中,没有生成额外的类,虽然MY_KEY的值将在运行时分配而不是常量,但在这种特定情况下它的使用方式没有区别。

So although I personally prefer #option 2, my analysis makes me think #option 1 is not worse, if not better. 所以虽然我个人更喜欢#option 2,但我的分析让我觉得#option 1并不差,如果不是更好的话。 I'm just wondering how other developers think about this and if there are any other benefits of #option 2 that I haven't thought of. 我只是想知道其他开发人员如何考虑这个问题以及#option 2是否还有其他任何我没有想过的好处。 Thanks. 谢谢。

Every time you write a (non-inline) lambda expression, you have created another class. 每次编写(非内联)lambda表达式时,都创建了另一个类。 Compared to that, creating a single class to hold top-level declarations seems minor. 与此相比,创建一个用于保存顶级声明的类似乎很小。

Furthermore, if all you have at the top level is a constant declaration, it will be inlined into each use site (by specification) so the owning class itself will become unreferenced and therefore targetable by ProGuard's minimization. 此外,如果您在顶层的所有内容都是一个常量声明,它将被内联到每个使用站点(按规范),因此拥有类本身将变为未引用,因此可通过ProGuard的最小化来定位。 It will most likely not appear in your production APK. 它很可能不会出现在你的制作APK中。

There is not only a semantic difference between the two options. 这两个选项之间不仅存在语义差异。

Option 1 ( val inside the class) is an instance field. 选项1(类中的val )是一个实例字段。

Option 2 (top-level const val ) is a top-level "static" member (roughly, since static doesn't exist in Kotlin.) 选项2(顶级const val )是顶级“静态”成员(粗略地说,因为Kotlin中不存在static )。

This is why you have a MyFragmentKt class generated: top-level members are compiled into a class of the name [Filename]Kt . 这就是生成MyFragmentKt类的原因:顶级成员被编译为名为[Filename]Kt

I would consider a third option: 我会考虑第三种选择:

class MyFragment {
    companion object {
        private const val MY_KEY = "my_key"
    }
}

This way, MY_KEY is (from Java) a static member of the MyFragment class, since JvmStatic is inferred for const variables. 这样, MY_KEY (来自Java)是MyFragment类的static成员,因为JvmStatic是为const变量推断的。 There will be a Companion class generated (but it will be empty). 将生成一个Companion类(但它将为空)。

Since your original approach was a field inside the class I feel like the companion object / static constant might be preferable. 由于你的原始方法是类中的一个字段,我觉得companion object / static常量可能更好。

More about companion object s vs Java's static 有关companion object与Java static更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM