skip to content

Explain the `field` identifier in a custom getter/setter. When does a property get a backing field, and what does referencing `field` mean?

level: middleimportance: must knowfreq 65%

answer

  1. field = the property's hidden storage
  2. Generated only if 'field' is referenced (or default accessor)
  3. Property name in accessor => StackOverflow recursion
  4. value = incoming setter parameter
  5. Initializer writes field directly, skips custom setter

basics

~10 s

Inside a custom getter or setter, field is a special name that refers to the property's own storage slot. The compiler only creates that storage if you actually use field, avoiding infinite recursion.

solid answer

~40 s

`field` is the **backing field** — the hidden storage behind a property — accessible only inside that property's accessors. The compiler generates a backing field if and only if at least one accessor references `field` (or the property uses a default accessor). You must use `field` instead of the property name inside accessors: writing the property name would re-enter the getter/setter and cause infinite recursion / a StackOverflowError. A custom setter typically validates or transforms `value` then writes `field = value`. A property whose accessors never touch `field` (e.g. a pure computed `get() = a + b`) has no backing field at all. This is how Kotlin lets you intercept reads/writes while still keeping the value stored.

code

kotlin · 9 lines
kotlin
class Temperature {
    var celsius: Double = 0.0
        set(value) {
            require(value >= -273.15) { "below absolute zero" }
            field = value          // stored
        }
    val fahrenheit: Double
        get() = celsius * 9 / 5 + 32   // no 'field' -> no backing field here
}

go deeper

for a junior

Knows field refers to the stored value and must be used inside the setter to assign.

for a middle

States the generation rule (backing field exists only if field is referenced or default accessor) and the recursion trap.

for a senior

Notes the initializer bypasses the custom setter and explains validation placement implications.

for a principal

Reasons about invariant enforcement: where validation can be defeated (initializer/reflection) and designs constructor + setter guards accordingly.

## Backing field defined When a property needs to store a value, the Kotlin compiler synthesizes a private **backing field** in the class — the real memory slot. You cannot name it directly from outside the accessors. Inside the accessors you reference it with the special keyword **`field`**. ## The rule: backing field is generated on demand Kotlin generates a backing field **only if**: - the property uses a **default** accessor (no custom get/set), or - a **custom** accessor references **`field`**. If neither holds (e.g. a getter that just returns other properties), there is **no** backing field — the property is purely computed. ## Why not use the property name inside accessors? Inside a getter, the property name *is* a call to the getter. So this recurses forever: ```kotlin var counter: Int = 0 get() = counter // BUG: calls the getter again -> StackOverflowError ``` Use `field` to touch the storage directly: ```kotlin var counter: Int = 0 get() = field // returns the stored value set(value) { field = value // writes the stored value } ``` ## Custom setter with validation/transformation The setter receives the incoming value as a parameter, conventionally named **`value`**. Validate/transform, then commit with `field = ...`. ```kotlin var name: String = "" set(value) { require(value.isNotBlank()) { "name blank" } field = value.trim() // store the cleaned value } ``` ## Initializer goes into the backing field For `var x: Int = 5`, the `= 5` initializer writes directly into the backing field — it does **not** invoke the custom setter. So setter validation does not run for the initializer; guard the constructor/init block separately if needed. ## Summary table - Uses `field` => backing field exists, value stored. - Never uses `field`, only derives => no backing field, computed each read. - Property name inside accessor => recursion bug; always use `field`.

  • What error do you get if you write the property name instead of field inside its own getter?
    Infinite recursion leading to a StackOverflowError at runtime, because the property name re-invokes the accessor.
  • Does a property's initializer (= 5) go through the custom setter?
    No. The initializer writes directly to the backing field, bypassing the custom setter, so setter validation does not run for it.

field is the safe-deposit box inside the property; the property name is the front-desk clerk. Inside the accessor you open the box directly instead of asking the clerk (who would just send you back to the box).

saying these in an interview costs you the question

  • Thinking every property always has a backing field
  • Using the property name inside its own accessor
  • Believing the initializer runs the custom setter
  • Claiming `field` is accessible from outside the property
  • Confusing `field` (storage) with `value` (setter parameter)

context