skip to content

::property.isInitialized

this::prop.isInitialized tells you whether a lateinit property has been assigned, so you can avoid the exception instead of catching it. It only works from inside the declaring class, which is the detail people miss.

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

questions

4

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

open as a page

Why can you only call `isInitialized` through `this::prop` from inside the declaring class, and not on another object's lateinit property from outside?

level: middleimportance: should knowfreq 40%

basics

~20 s

The check needs a direct reference to that exact property, which Kotlin only gives you where the property is visible — normally inside the class that declares it. From outside you usually can't form that reference, so you can't call the check.

open as a page

When is `lateinit` + `isInitialized` the right tool versus a nullable property or `by lazy`?

level: middleimportance: should knowfreq 45%

basics

~20 s

Use lateinit+isInitialized when a non-null value is set later by a framework and you sometimes need to ask 'is it set yet?'. Use nullable when absence is a normal value. Use by lazy when the value is computed once on first use.

open as a page

What are the failure modes and edge cases of `isInitialized` — type restrictions, concurrency, and what it does NOT guarantee?

level: seniorimportance: should knowfreq 30%

basics

~20 s

It only works on lateinit (no val, primitives, or nullable types), only inside the declaring class, and only tells you 'has been assigned' — not 'currently valid'. Under threads, true now doesn't guarantee the value is still usable later.

open as a page