4

It has been already clarified what's the difference between val and const val here.

But my question is, why we should use const keyword? There is no difference from the generated Java code perspective.

This Kotlin code:

class Application

private val testVal = "example"

private const val testConst = "another example"

Generates:

public final class ApplicationKt
{
    private static final String testVal = "example";
    private static final String testConst = "another example";
}
Marek J
  • 1,364
  • 8
  • 18
  • 33
  • 1
    Explicit is better than implicit. – Impulse The Fox Mar 22 '18 at 10:41
  • If you try assigning a value to a const after the initialisation, the compiler can pick this up as a possible bug. By defining a constant, you are telling the compiler (and developers, including yourself) that this value is not intended to change. – JNB Mar 22 '18 at 10:52
  • 1
    @JamesB What do you think happens if you try assigning a value to a non-`const` `val`? – Alexey Romanov Mar 22 '18 at 11:37
  • I'm surprised no-one mentioned this. The other BIG difference is the compiler will inline a const. Try reference testVal and testConst in Kotlin code to see what I mean. – Mikezx6r Mar 22 '18 at 23:54

6 Answers6

4

It's not always the same generated code.

If testVal and testConst were public, the generated code wouldn't be the same. testVal would be private with a public get, whereas testConst would be public, without any getter. So const avoids generating a getter.

JavierSA
  • 783
  • 1
  • 10
  • 25
  • 1
    That's true - for public fields we will have getter. But that would mean that for `private const val` we should be notified that `const` is a redundant modifier. – Marek J Mar 22 '18 at 11:12
2

In my opinion the main difference is that val means that no setter will be generated for the property (but a getter will be generated) and not that the value is constant, while a const val is a constant (like a Java's private/public static final xxx).

Example:

class Foo {
    private val testVal: String
        get() = Random().nextInt().toString()
}   
user2340612
  • 10,053
  • 4
  • 41
  • 66
2

As directly mentioned in the documentation, testConst can be used in annotation parameters, but testVal can't.

More generally speaking, const guarantees that you have a constant variable in the Java sense, and

Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1), reachability (§14.21), and definite assignment (§16.1.1).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
2

You don't see the difference between generated code because your variables are private. Otherwise the result would have the getter for testVal:

  public final class ApplicationKt {
       @NotNull
       private static final String testVal = "example";
       @NotNull
       public static final String testConst = "another example";

       @NotNull
       public static final String getTestVal() {
          return testVal;
       }
    }

So in your particular case it is the same, except you can use const properties in annotations:

const val testVal: String = "This subsystem is deprecated"
@Deprecated(testVal) fun foo() { ... }
Rainmaker
  • 10,294
  • 9
  • 54
  • 89
  • That's true - for private fields there is no difference. But that would mean that for private const val we should be notified that const is a redundant modifier. – Marek J Jan 26 '19 at 08:51
0

There are also differences in using them.

Example of constants(Kotlin):

class Constants {
    companion object {
        val EXAMPLE1 = "example1" // need companion and a getter
        const val EXAMPLE2 = "example2" // no getter, but companion is generated and useless
        @JvmField val EXAMPLE3 = "example3"; // public static final with no getters and companion
    }
}

How to use(Java):

public class UseConstants {
    public void method(){
        String ex1 = Constants.Companion.getEXAMPLE1();
        String ex2 = Constants.EXAMPLE2;
        String ex3 = Constants.EXAMPLE3;
    }
}
0

"Consts" are compile time Constants whereas "val" is used to define constants at run time. This means, that "consts" can never be assigned to a function or any class constructor, but only to a String or primitive.

Example:

const val NAME = "M Sakamoto"
val PICon = getPI()

fun getPI(): Double {
 return 3.14
}

fun main(args: Array<String>) {
  println("Name : $NAME")
  println("Value of PI : $PICon")
 }

Output:

Name : M Sakamoto
Value of PI : 3.14
Farid Haq
  • 3,728
  • 1
  • 21
  • 15