In Kotlin, the const val modifier is used only for compile-time constants at the top level (file level), or inside objects (object) and companion objects. Properties declared as val inside classes become regular final properties without static initialization. An important feature: const val cannot be inherited, while val can be overridden (if permitted).
Constants (const val) cannot be abstract as they must have a value at compile time. Regular val allows implementing the constant pattern in hierarchies through open properties; however, at runtime they will be accessible through a getter, which differs from compilation in Java.
open class Base { open val info: String = "base" } class Child : Base() { override val info = "child" } object Constants { const val APPLICATION_NAME = "MyApp" }
Can
const valbe declared in an interface or an abstract class and then overridden/inherited?
No. In Kotlin, const val cannot be declared inside an interface or an abstract class — this is only allowed at the object level (object) and top-level. There are no equivalent static final variables available for inheritance.
interface Foo { // const val X = "constant" // compile error: const 'val' are only allowed on top-level, in objects, or in companion objects }
Story
The team tried to reuse string constants through interface inheritance in several Android modules, declaring them as
const val— they encountered a compile error and had to move the constants to the top level, which worsened encapsulation.
Story
In the project, all Java static final fields were converted to Kotlin
valproperties in open classes, expecting the same behavior (compile-time const), but they became regular properties with a getter. As a result, access time increased, negatively impacting the hot paths of the microservice application.
Story
When porting Java constant containers to Kotlin, developers made constants inside the companion object, but encountered an access problem from Java code: constants were visible as fields of the companion itself, not the class, causing confusion in the API and additional interoperability bugs.