skip to content

What does `this::myProp.isInitialized` do, and why would you use it on a `lateinit var`?

level: juniorimportance: must knowfreq 55%

answer

  1. Bound property reference: this::prop
  2. Returns Boolean: assigned yet?
  3. Avoids UninitializedPropertyAccessException
  4. lateinit only, declaring class only
  5. Alternative when no 'unset' state: by lazy

basics

~20 s

It checks whether a lateinit property has already been given a value. If you read a lateinit property before it is set, the app crashes; this check lets you ask 'is it set yet?' first and avoid the crash.

solid answer

~40 s

`isInitialized` is a property on a bound property reference (`this::myProp`) that returns a `Boolean` saying whether a `lateinit var` has been assigned. Reading an uninitialized `lateinit` throws `UninitializedPropertyAccessException`; calling `this::myProp.isInitialized` first lets you branch safely without try/catch. It only works on `lateinit` properties, and only from inside the declaring class via a property reference to that property. Typical use: a property set in `onCreate`/`@PostConstruct` or by a framework where you can't guarantee assignment happened before some method runs, so you guard the read. It is not for ordinary nullable types — those use `?.`/`!= null` instead. The check is essentially asking the backing field 'do you hold a real value yet?'.

code

kotlin · 6 lines
kotlin
class Service {
    private lateinit var conn: String
    fun connect() { conn = "open" }
    fun status(): String =
        if (this::conn.isInitialized) conn else "not connected"
}

go deeper

for a junior

Knows lateinit can crash on early read and that isInitialized guards against it.

for a middle

Names the exception, the bound-reference syntax this::prop, and the lateinit-only constraint.

for a senior

Explains it returns Boolean for assignment (not null), the declaring-class scope limit, and when by lazy is the better tool.

for a principal

Frames isInitialized as a code-smell signal: needing it often means the lifecycle/DI model leaks an unset window that design could remove.

## What `lateinit` is `lateinit var` lets you declare a non-null `var` property without an initializer, promising the compiler you'll assign it before first read. It's used when a value is injected or set by a lifecycle method (Android `onCreate`, Spring `@PostConstruct`, test `@BeforeEach`) and a nullable type would force noise (`?.`, `!!`) everywhere. The cost: if you **read** the property before assigning it, Kotlin throws `kotlin.UninitializedPropertyAccessException: lateinit property X has not been initialized`. ## The `isInitialized` check `isInitialized` is a `val` defined as an extension on a **bound property reference** of a `lateinit` property. You access it through the `::` operator: ```kotlin class Repo { private lateinit var cache: Map<String, Int> fun warm(values: Map<String, Int>) { cache = values } fun lookup(key: String): Int? = if (this::cache.isInitialized) cache[key] else null } ``` - `this::cache` is a **bound property reference** (`KProperty0<Map<String, Int>>` bound to `this`). - `.isInitialized` returns `true` once `cache` has been assigned, `false` otherwise. - It avoids both the crash and an ugly `try { cache } catch (e: UninitializedPropertyAccessException) { ... }`. ## Hard constraints - **Only on `lateinit` properties.** A plain `val`/`var` reference has no `isInitialized`; it won't compile. - **Only from inside the declaring class** (or a subclass for accessible properties) — you reference the property via `this::prop` or `prop::name` patterns within scope. You cannot call `someOtherObject::prop.isInitialized` from outside; the reference must resolve to a `lateinit` you can see. - **Not for `val`, primitives, or nullable types.** `lateinit` itself forbids primitives and nullable types, so `isInitialized` inherits those limits. ## When to reach for it - Guarding a read in a method that might run before the init hook. - Idempotent lazy setup: `if (!this::client.isInitialized) client = build()`. - Avoiding `UninitializedPropertyAccessException` in teardown/`onDestroy` when init may have been skipped. Prefer `by lazy { }` when the value is computed once on first access and you never need the 'not yet set' state — `lazy` removes the need for `isInitialized` entirely.

  • What exception do you get if you read a lateinit property before assignment?
    kotlin.UninitializedPropertyAccessException, with a message naming the property.
  • Can you use isInitialized on a regular (non-lateinit) var?
    No. It is only available on a property reference to a lateinit property; otherwise it doesn't compile.

Like checking if a mailbox already has a letter before reaching in, instead of getting bitten because it's empty.

saying these in an interview costs you the question

  • Thinking isInitialized works on any nullable or ordinary property
  • Saying it checks for null (it checks assignment, not nullness)
  • Using a try/catch on UninitializedPropertyAccessException instead of the check
  • Believing reading an unset lateinit returns null instead of throwing

context