What is the difference between val, var, and const val?
Understand reassignment, mutation, and compile-time constants in Kotlin.
What the interviewer is testing
This question sounds like it's about Kotlin keywords, but it rarely is.
Interviewers already know you can memorise what val, var, and const val do.
What they're trying to discover is whether you understand what is allowed to change, who owns that change, and why some values have to exist before your application starts running.
That's the difference between someone who knows Kotlin syntax and someone who understands Kotlin's design.
❌ Common mistake
If they ask you to elaborate
Reassignment and mutation are different things
This is the distinction that makes val click.
val session = UserSession("abc")You cannot later make session refer to a different UserSession.
But if UserSession itself exposes mutable state, that state may still change. val controls the assignment to session; it does not reach inside the object and make the whole object immutable.
With var, reassignment is part of the design:
var selectedTab = 0
selectedTab = 1Here the value represented by selectedTab genuinely changes over time, so reassignment is expected rather than accidental.
Why const val exists
A normal val can be calculated while your program is running:
val apiUrl = buildApiUrl()That is perfectly valid because Kotlin only needs apiUrl once that code executes.
A const val is different. The compiler must be able to determine the value from the declaration itself:
const val EXTRA_USER_ID = "extra_user_id"That is why const val is restricted to primitive types and String, must be initialized with a compile-time constant expression, and can only be declared at the top level or inside an object or companion object.
You commonly see these constants used for things such as stable Intent or Bundle keys. Compile-time constants are also needed in places where Kotlin requires a value before runtime, such as certain annotation arguments.
Production considerations
The useful part of val is not that it makes code "more Kotlin." It makes a promise to the next person reading the code: this name will not be reassigned somewhere later.
That matters most when state starts moving through ViewModels, repositories, controllers, or long-lived objects. If something is declared as var, the reader has to consider that the value may be replaced elsewhere. If reassignment is not part of the design, there is little reason to expose that extra possibility.
The same idea applies to APIs. A class can keep mutable state internally while exposing a read-only view of it:
class Cart {
private val _items = mutableListOf<Item>()
val items: List<Item> = _items
fun add(item: Item) {
_items += item
}
}Callers can observe items, but they do not own the mutation. The Cart keeps control of how its state changes.
Use const val when you actually need a compile-time constant, not because it looks "more constant" or as a performance trick. A value that is discovered from configuration, a database, resources, dependency injection, or another runtime source is simply not a const val problem.