Home » Android » android – Kotlin: const val vs val

android – Kotlin: const val vs val

Posted by: admin April 23, 2020 Leave a comment

Questions:

I understand in Kotlin const val is used to declare constants and val is for readonly properties. 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. I’m wondering which one of the following 2 options is better:

Option 1:

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

Option 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. However since it’s declared on the top level, it costs a class i.e. MyFragmentKt (assume the file name is MyFragment.kt) to be created in the compiled java code. 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.

So although I personally prefer #option 2, my analysis makes me think #option 1 is not worse, if not better. 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. Thanks.

How to&Answers:

Every time you write a (non-inline) lambda expression, you have created another class. 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. It will most likely not appear in your production APK.

Answer:

There is not only a semantic difference between the two options.

Option 1 (val inside the class) is an instance field.

Option 2 (top-level const val) is a top-level “static” member (roughly, since static doesn’t exist in Kotlin.)

This is why you have a MyFragmentKt class generated: top-level members are compiled into a class of the name [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. There will be a Companion class generated (but it will be empty).

Since your original approach was a field inside the class I feel like the companion object/static constant might be preferable.

More about companion objects vs Java’s static