What is the difference between val and var in Kotlin, and why is val-first considered idiomatic?
answer
- val = read-only reference, var = reassignable
- val fixes the reference, not the object's contents
- MutableList in a val can still be mutated
- val enables smart casts on locals
- val can have a custom getter (recomputes)
basics
~10 sval makes a read-only reference you can't reassign; var makes a reassignable one. Kotlin prefers val first because it makes code safer and easier to reason about.
solid answer
~40 sval declares a read-only reference: once assigned it cannot be reassigned (the compiler rejects reassignment). var declares a mutable reference that can point to a new value later. Idiomatic Kotlin reaches for val first and only switches to var when reassignment is genuinely needed; this reduces accidental mutation and makes data flow easier to follow. A key nuance: val controls the reference, not deep immutability. A val pointing to a MutableList can still have items added — the binding is fixed, the object's contents are not. For real immutability you also need an immutable type (List vs MutableList). val also enables smart casts on local variables, since the compiler knows the value won't change between a null-check and its use.
code
kotlin · 6 linesval list = mutableListOf(1, 2)
list.add(3) // allowed: mutating contents
// list = mutableListOf() // error: reassigning a val
var total = 0
for (n in list) total += n // var reassigned each stepgo deeper
States the basic rule: val can't be reassigned, var can; should prefer val.
Distinguishes reference immutability from object immutability and ties val to List vs MutableList.
Connects val to smart casts, computed val getters, and concurrency implications.
Frames val-first as a default that constrains mutable state, improving local reasoning and reviewability across a codebase.
## val vs var Kotlin has two keywords to introduce a variable: - **`val`** ("value") declares a **read-only** reference. After it is assigned once, you cannot reassign it — the compiler emits an error if you try. Think "final reference". - **`var`** ("variable") declares a **reassignable** reference. You may point it at a different value later. ```kotlin val name = "Ada" // read-only // name = "Bob" // compile error: val cannot be reassigned var count = 0 // reassignable count = count + 1 // fine ``` ## `val` is about the reference, not deep immutability A `val` fixes *which object the name points to*. It does **not** freeze that object's internal state. ```kotlin val list = mutableListOf(1, 2) list.add(3) // OK — we mutate the object, not the reference // list = mutableListOf() // compile error — reassigning the val is not allowed ``` For genuine immutability you pick an immutable **type** as well: `List` (read-only interface) instead of `MutableList`. ## Why val-first is idiomatic - **Fewer moving parts**: a name that never changes is easier to reason about. - **Safer concurrency**: read-only references can't be reassigned out from under you. - **Enables smart casts**: because the compiler knows a local `val` won't change, after `if (x != null)` it can treat `x` as non-null without a manual cast. A `var` (especially a property) may not get this guarantee. ## `val` with a custom getter A `val` can be backed by a `get()` that recomputes each access, so "read-only" does not always mean "constant": ```kotlin val now: Long get() = System.currentTimeMillis() ``` This returns a different value each call, yet is still a `val` (no setter, cannot be reassigned).
- Does val guarantee thread safety?No. It prevents reassignment of the reference, but if the referenced object is mutable, concurrent mutation is still unsafe. Use an immutable type or synchronization.
- Can a val ever return different values on different reads?Yes, if it is defined with a custom get() that recomputes (e.g. a derived/computed property). It still can't be reassigned.
val is like a name tag glued to one person; you can't move the tag, but that person can still change their haircut.
saying these in an interview costs you the question
- Claiming val means the object is fully immutable
- Saying val and var are interchangeable with no real difference
- Thinking val is like C's const for deep constness
- Defaulting to var everywhere out of habit
- Believing val blocks mutation of a MutableList's contents