Lateinit Usage
ID |
kotlin.lateinit_usage |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Kotlin |
Tags |
best-practice, reliability |
Description
Flags property declarations that carry the lateinit modifier. lateinit opts a
property out of Kotlin’s null-safety system: the type stays non-nullable but the
compiler no longer enforces that a value has been assigned before the first read.
Rationale
class Service {
lateinit var client: Client
}
Reading client before the application has assigned a value throws
UninitializedPropertyAccessException at runtime. The construct defers what the
type system normally catches at compile time to an unspecified later moment,
producing crashes that depend on initialisation order, threading, or framework
lifecycles.
Common causes of lateinit failures include constructor-injection frameworks
that did not actually inject the property, test setup methods that skipped a
step, and Android lifecycle callbacks that fire before onCreate. None of these
are surfaced by the type — every read is a leap of faith.
Remediation
class Service {
// Compute on first access; thread-safe.
val client: Client by lazy { buildClient() }
}
class Service {
// Keep the value in the type system; force callers to handle the null case.
var client: Client? = null
}
-
by lazy { … }initialises on first read and removes the failure mode entirely. -
A nullable property with an explicit
nullinitial value documents the "may not be ready yet" state in the type, so the compiler forces callers to handle it.