What is the difference between val and var in Kotlin, and when should you reach for each?
answer
- val = assign-once binding; var = reassignable
- val freezes the reference, not the object
- Both are statically typed (inference or annotation)
- val-first idiom: default val, var only when needed
- val helps smart-casts
basics
~10 sval means you set the value once and cannot reassign it. var means you can reassign it later. Prefer val by default and use var only when the value really needs to change.
solid answer
~40 sval declares a read-only (assign-once) binding: the compiler rejects any later reassignment to that name. var declares a mutable binding you can reassign as many times as you like. Both are statically typed; you can rely on type inference (val x = 1) or annotate (val x: Int = 1). The idiomatic Kotlin style is val-first: reach for val by default and only switch to var when a value genuinely needs to be reassigned (loop accumulators, mutable state). val-first improves readability (the reader knows the name won't change), helps the compiler with smart-casts, and reduces accidental-mutation bugs. Note val constrains the reference, not the object behind it.
code
kotlin · 8 linesval pi = 3.14 // assign-once
// pi = 3.15 // compile error
var total = 0
for (n in 1..5) total += n // var legitimately reassigned
val list = mutableListOf(1)
list.add(2) // allowed: object is mutable, binding is notgo deeper
States that val is assign-once and var is reassignable, and prefers val by default.
Articulates that val constrains the reference not the object, and that val enables smart-casts.
Frames val-first as a design discipline reducing mutable state and explains property getter/setter generation differences.
Connects val-first to broader immutability-by-default architecture and reasoning about concurrency/state.
## The two keywords Kotlin has exactly two ways to introduce a local variable or property: - **`val`** — a *read-only* (assign-once) binding. Once initialized, the name cannot be reassigned. Think "value" or "final reference". - **`var`** — a *mutable* binding. You can reassign it any number of times. Think "variable". ```kotlin val name = "Ada" // read-only // name = "Bob" // COMPILE ERROR: val cannot be reassigned var count = 0 count = 1 // OK count += 1 // OK ``` ## "Read-only" is about the binding, not the object `val` freezes the *reference*, not the object it points to. A `val` holding a `MutableList` still lets you mutate the list: ```kotlin val items = mutableListOf(1, 2) items.add(3) // OK — mutating the object // items = mutableListOf() // ERROR — reassigning the binding ``` So `val` ≠ deep immutability. (That distinction is the heart of a separate question.) ## Type inference vs. explicit type Both keywords are statically typed. The type can be **inferred** from the initializer or **annotated** explicitly: ```kotlin val a = 42 // inferred Int val b: Long = 42 // explicit var c: String? = null ``` ## val-first idiom — why it's the default The community style (and IntelliJ inspections) push **`val` by default, `var` only when needed**. Benefits: - **Readability** — a reader sees `val` and knows the name's value never changes within scope. - **Smart casts** — the compiler can smart-cast a `val` after a null check because it can't change between the check and use; a mutable `var` (especially a property) often blocks smart-casting. - **Fewer bugs** — accidental reassignment is caught at compile time. Use `var` for genuine mutable state: loop accumulators, counters, builders, or fields whose value evolves over an object's lifetime. ## Where they appear Both work as **local variables** and as **properties** of classes/objects. As a property, `val` generates only a getter; `var` generates a getter and a setter. (A `val` property can still be backed by a custom getter that returns different values — but the *stored* backing field, if any, is assigned once.)
- Does val make the object immutable?No. val only prevents reassigning the name. If the object itself is mutable (e.g. MutableList), you can still mutate its contents.
- Why prefer val over var?Readability, fewer accidental-mutation bugs, and it enables smart-casts because the compiler knows the value can't change.
val is a name tag glued onto one box; var is a sticky note you can peel off and slap onto a different box.
saying these in an interview costs you the question
- Claiming val makes the referenced object deeply immutable
- Saying var is generally preferred or 'more flexible so use it'
- Thinking val means the value is a compile-time constant (that's const)
- Believing val and var have different runtime performance characteristics
- Not knowing both can be inferred or explicitly typed