skip to content

What is the difference between a `val` and a `var` property in Kotlin, and what does the compiler generate for each?

level: juniorimportance: must knowfreq 85%

answer

  1. val = getter only, var = getter + setter
  2. val freezes the reference, not the object
  3. Val cannot be reassigned (compile error)
  4. Java sees getX()/setX()
  5. one assignment allowed for val

basics

~10 s

A val is read-only — you set it once and can't reassign it. A var can be reassigned. The compiler creates a getter for both, and a setter only for var.

solid answer

~40 s

A property declared with `val` is read-only: it generates a backing field and a public getter, but no setter, so you cannot reassign it after initialization. A `var` is mutable: it generates a backing field, a getter, and a setter. `val` means the reference is fixed, not that the referenced object is immutable — a `val list = mutableListOf(...)` can still have elements added. Reassignment of a `val` is a compile error (`Val cannot be reassigned`). For class properties, Kotlin synthesizes the accessors; from Java you call `getX()`/`setX()`. A `val` can also be backed by a custom getter computed on each access instead of a stored field.

code

kotlin · 7 lines
kotlin
class Counter {
    val createdAt = System.currentTimeMillis() // read-only
    var count = 0                              // mutable

    fun inc() { count++ }   // OK: var has a setter
    // fun reset() { createdAt = 0L } // error: Val cannot be reassigned
}

go deeper

for a junior

Knows val is read-only and var is mutable, and that reassigning a val fails to compile.

for a middle

Explains accessor synthesis (getter for val, getter+setter for var) and shallow immutability of val.

for a senior

Discusses Java interop method names, when val is computed via a custom getter vs a stored field, and immutability design.

for a principal

Frames val/var choice as an API-design and concurrency decision (immutable references aid thread-safety) across module boundaries.

## What is a property? In Kotlin a **property** is a class member that combines a (possibly hidden) **field** with **accessors** (a getter, and for mutable properties a setter). You never declare a raw Java-style field directly; you declare a property and the compiler synthesizes the accessors. ## `val` vs `var` - **`val`** (value) — *read-only*. Exactly one assignment is allowed (at declaration, in an `init` block, or in the constructor). The compiler generates a **getter only**. Reassigning later is a compile error: `Val cannot be reassigned`. - **`var`** (variable) — *mutable*. The compiler generates a **getter and a setter**, so it can be reassigned any number of times. ```kotlin class User(val id: Long, var name: String) val u = User(1, "Ana") u.name = "Bob" // OK — var has a setter // u.id = 2 // compile error — val has no setter ``` ## What the compiler generates For a simple property the compiler creates: - a private **backing field** (referenced inside accessors via the keyword `field`), - a `getX()` method, - a `setX()` method **only for `var`**. These are the methods Java code sees (`user.getId()`, `user.setName("Bob")`). ## `val` is shallow immutability `val` freezes the *reference*, not the object it points to: ```kotlin val items = mutableListOf(1, 2) items.add(3) // OK — the list object is mutable // items = mutableListOf() // error — can't rebind the val ``` For a deeply immutable collection use a read-only type like `List` plus `val`. ## Local vs member Both keywords work for **local variables** and **class properties**. Local `val`/`var` are just stack variables with no accessors; member properties get synthesized accessors as described above.

  • Does `val` make the referenced object immutable?
    No. It only prevents reassigning the reference. A `val` holding a MutableList can still be mutated via add/remove.
  • Can a `val` be initialized somewhere other than the declaration line?
    Yes — in the primary constructor parameter, an init block, or a secondary constructor, as long as it's assigned exactly once on every path before use.

A val is a name tag stuck to a box: you can change what's inside the box, but you can't move the tag to a different box.

saying these in an interview costs you the question

  • Saying `val` makes the object deeply immutable
  • Claiming `val` generates no getter
  • Thinking `var` has no backing field
  • Confusing `val` with Java `final` on a collection's contents

context