To val, or to const val, that is the question

Patxi Bocos
Oct 17 · 2 min read

When starting to learn Kotlin, one of the main observable differences compared to Java is that every variable/value definition comes first with any of these three keywords: var, val or const val.

It is pretty clear that var allows mutation while val defines immutability. There is no chance that any val or const val can change the object they are referencing or the value they contain. But there seems to be a lot of confusion/discussion about when to use val or const val.

We need to take a look at the compiled bytecode generated by Kotlin to discover an important different between these two.

Observing the bytecode

Let’s say that we have these two definitions in a ConstVal.Kt Kotlin file:

and we are using them from a Java class:

Decompiling the generated class file for our Kotlin code we get:

Both values are defined as final, the only difference is that const val is declared as public while val is private (including a getter).

Compiling it

Let’s plug in all this together and make it run! The first needed step is to build the Kotlin source in order to generate a separate jar file. For that we just need to execute kotlinc command included in the Kotlin compiler:

> kotlinc ConstVal.kt -d constval.jar

-d option allows specifying a custom destination for generated class files.

Now we can compile Java source using the previously generated jar:

> javac -cp constval.jar ConstValFromJava.java

That command will generate the .class file that would be executable with:

> java -cp constval.jar; ConstValFromJava
1
2

The result of it will be printing 1 and 2 as expected. But let’s see what happens if we change that values in the source and then rebuild the jar.

Updating Kotlin sources

and compiling again:

> kotlinc ConstVal.kt -d constval.jar

What do you think that will happen if we just execute Java class again?

> java -cp constval.jar; ConstValFromJava
3
2

It shows 3 and 2! Not 3 and 4 as we could expect 😱

Inlined value

This is the expected behavior, and there is a reason for this to happen. If we decompile the generated Java class file, we can observe the code:

It happens that our FANCY_CONST_VAL is not referenced from Java code. The value has been inlined, so if we don’t recompile our Java program we will hold the old value, and not a reference to the original definition.

This is a strong reason for the compiler to force us to know the exact value of a const at compile time. If the values were not known then the compiler would not be able to inline anything.

Happy Kotlin programming and beware of using val or const val 😉

Patxi Bocos

Written by

Impure developer and functional programming enthusiast

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade