skip to content

val vs var

val gives you a binding you can assign once, var one you can reassign, and idiomatic Kotlin reaches for val first. The follow-up interviewers love is that val freezes the reference, not the object behind it, so a val MutableList is still mutable.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What is the difference between val and var in Kotlin, and when should you reach for each?

level: juniorimportance: must knowfreq 92%

answer

  1. val = assign-once binding; var = reassignable
  2. val freezes the reference, not the object
  3. Both are statically typed (inference or annotation)
  4. val-first idiom: default val, var only when needed
  5. val helps smart-casts

basics

~10 s

val 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 s

val 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 lines
kotlin
val 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 not

go deeper

for a junior

States that val is assign-once and var is reassignable, and prefers val by default.

for a middle

Articulates that val constrains the reference not the object, and that val enables smart-casts.

for a senior

Frames val-first as a design discipline reducing mutable state and explains property getter/setter generation differences.

for a principal

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

context

open as a page

Explain why `val` does not guarantee immutability. How do you actually express an immutable value in Kotlin?

level: middleimportance: must knowfreq 78%

basics

~20 s

val only stops you from pointing the name at a different object. The object it points to can still change if it is mutable. For real immutability you also need an immutable type, like List instead of MutableList.

open as a page

What are the initialization rules for val? Can a val be assigned later, conditionally, or remain uninitialized?

level: middleimportance: should knowfreq 55%

basics

~20 s

A val must be set exactly once before it is read. You can split the declaration and the assignment, and even assign it in different branches of an if, as long as every path sets it once and you never read it before then.

open as a page

How do val and var differ for class properties (getters/setters), and why can a var property block a smart cast?

level: seniorimportance: should knowfreq 64%

basics

~20 s

A val property only gets a getter; a var property gets a getter and a setter. A var (especially a public or open one) can change between a null check and its use, so the compiler refuses to smart-cast it because the value might no longer be non-null.

open as a page

How do val and var compile on the JVM, and what does that mean for Java interop and the meaning of 'final'?

level: seniorimportance: nice to knowfreq 38%

basics

~20 s

A val property becomes a Java getter method, and a var adds a setter. A local val compiles to a final local variable. val controls reassignment in Kotlin, but Java code calling the getter just sees a normal method, so val is not a deep immutability promise across the boundary.

open as a page