lateinit & lazy in Kotlin
In Kotlin, all variables must be initialized before use — this ensures null safety and prevents
runtime crashes. However, there are cases where initialization can’t happen immediately.
To handle such scenarios, Kotlin provides two smart property initialization options:
lateinit and lazy.
lateinit and lazy?Kotlin enforces initialization at declaration to ensure safety. But sometimes:
That’s where lateinit (for variables) and lazy (for read-only properties) come into play.
lateinit – Late Initialization for varlateinit?
The lateinit keyword tells the compiler that you’ll initialize the variable later,
but before using it. It’s mainly used for non-nullable mutable properties (var).
lateinit var variableName: Type
class Student {
lateinit var name: String // Declaration without initialization
fun assignName() {
name = "Talha Abbas"
}
fun printName() {
if (this::name.isInitialized) { // Check before using
println("Student Name: $name")
} else {
println("Name not initialized yet.")
}
}
}
fun main() {
val s = Student()
s.printName()
s.assignName()
s.printName()
}
Here, name is initialized later using assignName(),
but not at declaration. Accessing it before initialization will throw
UninitializedPropertyAccessException.
You might notice that lateinit works with String even though you can’t use it
with primitives like Int or Boolean.
That’s because in Kotlin, String is an object type (a reference type), not a primitive.
Kotlin restricts lateinit to reference types only — it cannot be applied to
primitive or nullable variables since those are represented differently in memory.
lateinitvar (mutable properties).val, primitive types (Int, Boolean, etc.), or nullable types.
class MainActivity : AppCompatActivity() {
lateinit var button: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.submitBtn)
button.setOnClickListener {
Toast.makeText(this, "Clicked!", Toast.LENGTH_SHORT).show()
}
}
}
Here, the button can’t be initialized before setContentView(),
so lateinit is the perfect solution.
lazy – Lazy Initialization for vallazy?
The lazy delegate is used to initialize a read-only (val) property
only when it’s accessed for the first time. It’s part of Kotlin’s Delegation feature.
val variableName: Type by lazy {
// initialization logic
}
class User {
val info: String by lazy {
println("Initializing user info...")
"User: Talha Abbas"
}
}
fun main() {
val user = User()
println("Before accessing info")
println(user.info) // Triggers initialization
println(user.info) // Uses cached value
}
Output:
Before accessing info
Initializing user info...
User: Talha Abbas
User: Talha Abbas
The initialization block runs only once, the first time the property is accessed. The value is then cached for subsequent uses.
val data by lazy(LazyThreadSafetyMode.NONE) {
println("Loading data...")
"Data loaded"
}
lateinit and lazy| Aspect | lateinit |
lazy |
|---|---|---|
| Type | Used with var (mutable) |
Used with val (immutable) |
| Initialization Time | Initialized later manually | Initialized automatically on first access |
| Thread Safety | Not thread-safe | Thread-safe by default |
| Use Case | Dependency Injection, Android Views | Heavy Computation, Config Loading, Caching |
| Null Safety | Cannot be used with nullable types | Works with all types |
lateinit and lazy?
Answer: lateinit is used for mutable variables (var) that will be initialized later,
while lazy is used for immutable properties (val) that are initialized only when accessed
for the first time.
lateinit with primitive types like Int or Boolean?Answer: No. lateinit cannot be used with primitive types or nullable variables,
but works with String since it’s a reference type in Kotlin.
lazy thread-safe?
Answer: Yes, by default lazy uses LazyThreadSafetyMode.SYNCHRONIZED,
which ensures that initialization happens safely in multi-threaded environments.
lateinit in Android?
Answer: It’s commonly used for UI elements that are initialized after setContentView()
is called, e.g., lateinit var button: Button.
lateinit variable before it’s initialized?Answer: It throws UninitializedPropertyAccessException.
lazy properties be reinitialized?Answer: No, once initialized, a lazy property cannot be reassigned.
lateinit variable is initialized?
Answer: Use the reflection syntax:
if (this::variableName.isInitialized).
Both lateinit and lazy enhance flexibility in Kotlin’s initialization mechanism.
Use lateinit when a variable’s value will be set later (like Android views),
and lazy when a property should be initialized only when accessed (like configuration or caching).
Understanding when and how to use each is a key concept in writing clean, efficient Kotlin code.