lateinit & lazy
lateinit and lazy are two ways to delay initialization: lateinit var lets you set a non-null property later by hand, while by lazy computes a val automatically on first access and caches it.
Learn lateinit & lazy in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Both avoid giving a value before you actually have one — you'll learn exactly when to reach for each.
What You'll Learn in This Lesson
1️⃣ lateinit var — Initialize Later
A lateinit var declares a non-null property with no initial value, promising you'll assign it before any read. This is common when a framework or a setup step provides the value after the object is constructed.
Reading a lateinit property before it's set throws an exception. You can check first with ::prop.isInitialized :
2️⃣ by lazy — Compute Once, On First Access
The by lazy {' '} delegate runs its block the first time the property is read, then caches the result. Later reads return the cached value without re-running the block. It's ideal for expensive values you might not even need.
3️⃣ Eager val vs lazy val
A regular val is computed eagerly — right where it's declared. A by lazy val is computed lazily — not until something reads it. Watch the print order to see exactly when each block runs.
Your turn. Fill in the ___ blank, then run and compare.
Prove that lazy computes only once: the "connecting..." line must appear a single time even though you read the value twice.
📋 Quick Reference — lateinit & lazy
Practice quiz
What does 'lateinit var' promise the compiler?
- The value is computed automatically
- A non-null value will be assigned before it is read
- The property is immutable
- The value is always null
Answer: A non-null value will be assigned before it is read. lateinit var declares a non-null property you promise to set before reading it.
What happens if you read a lateinit property before assigning it?
- It returns null
- It returns an empty string
- It throws UninitializedPropertyAccessException
- It returns zero
Answer: It throws UninitializedPropertyAccessException. Reading a lateinit property too early throws UninitializedPropertyAccessException.
How do you check whether a lateinit property has been set?
- prop != null
- prop.isSet()
- ::prop.isInitialized
- prop.exists
Answer: ::prop.isInitialized. Use the ::prop.isInitialized check to guard against reading too early.
Which of these can lateinit be applied to?
- A val
- An Int property
- A var of a non-null reference type
- A computed property
Answer: A var of a non-null reference type. lateinit works only on a var of a non-null reference type — not val or primitives.
When does a 'by lazy { }' block run?
- The first time the property is read
- At program startup
- Every time it is read
- When the object is constructed
Answer: The first time the property is read. The lazy block runs once, on first access, then caches its result.
How many times does a lazy block run if the property is read three times?
- Three times
- Once
- Zero times
- Twice
Answer: Once. lazy runs the block once and caches; later reads return the cached value.
When is a normal val computed?
- Lazily, on first read
- Never
- Eagerly, right where it is declared
- Only inside main()
Answer: Eagerly, right where it is declared. A regular val is computed eagerly, at the point of declaration.
Which delegate is appropriate for a deferred val of type Int?
- lateinit var
- by lazy
- a nullable Int
- an abstract property
Answer: by lazy. lateinit can't be used on Int or val, so use by lazy for a deferred Int val.
Why might you choose lateinit over a nullable type?
- It allows null safely
- It recomputes automatically
- It avoids handling null on every access for a value you know will be set
- It is faster to compute
Answer: It avoids handling null on every access for a value you know will be set. lateinit gives a non-null var so code skips ?. / !! checks for a value set later.
By default, is a lazy property thread-safe?
- Yes, it is synchronized by default
- No, never
- Only on Android
- Only for val of Int
Answer: Yes, it is synchronized by default. By default lazy uses synchronized mode, making first access thread-safe.