lateinit var vs. val by lazy in Android

Tests your grasp of Kotlin's non-nullable property initialization. Define lateinit (mutable, framework-init) vs. lazy (immutable, deferred-init). Use lateinit for Views in onCreate and lazy for expensive objects. Red flag: confusing their mutability.
What's really being asked
This question probes your understanding of Kotlin's mechanisms for handling non-nullable types when immediate initialization isn't possible. It's not just about definitions; it's about demonstrating practical judgment. The interviewer wants to see if you understand the trade-offs between mutability (lateinit var), immutability (val by lazy), thread safety (lazy), and performance implications in the context of the Android framework's lifecycle.
The full answer
A strong answer explains four key points in order. First, define lateinit var: it's a mutable (var) promise that a non-nullable property will be initialized before its first access, typically by an external source like the Android framework. Accessing it before initialization throws an UninitializedPropertyAccessException. It cannot be used with primitive types. Second, define val by lazy: it's an immutable (val) property whose value is computed only upon its first access. The initializer lambda is, by default, thread-safe and synchronized. The result is cached and returned on all subsequent calls. Third, summarize the core difference: lateinit is for mutable properties whose value is supplied later, while lazy is for immutable properties whose value is expensive to create and should be deferred. Fourth, provide concrete Android scenarios for each.
The mistakes people make
The most common mistake is treating them as interchangeable. A candidate who suggests using lazy for a property that needs to be reassigned (like a View that gets nulled out in onDestroyView) or lateinit for a computationally expensive, single-initialization object (the prime use case for lazy) reveals a fundamental misunderstanding. Forgetting that lateinit is for var and lazy is for val is another major red flag. A senior candidate should also know the failure mode (UninitializedPropertyAccessException) and how to check for it (this::myVar.isInitialized).
What usually comes next
Expect questions like: "How can you check if a lateinit var has been initialized?" (Answer: this::myVar.isInitialized). "What are the different thread safety modes for by lazy?" (Answer: SYNCHRONIZED, PUBLICATION, NONE). "Why can't you use lateinit on a primitive type like Int?" (Answer: On the JVM, primitives have default values like 0, so there's no special value like null to represent an 'uninitialized' state for the compiler to check against).
A concrete example
A perfect lateinit scenario is for a RecyclerView.Adapter in a Fragment. You declare it as private lateinit var userAdapter: UsersAdapter. It cannot be initialized in the constructor because it requires a Context. You then initialize it in onViewCreated, for example: userAdapter = UsersAdapter() and assign it to your RecyclerView. A perfect by lazy scenario is for an expensive, read-only object. For instance, private val analyticsTracker: AnalyticsTracker by lazy { AnalyticsTracker(requireContext()) }. The AnalyticsTracker object, which might take 150ms to set up, is only created if and when it's actually used, and the same instance is reused thereafter.
Interview question
An Android Fragment needs a property for a complex, computationally expensive object that is only used in certain user flows. The object should be created only once. Which declaration is most appropriate?
- a.private lateinit val myObject: MyObject
- b.private val myObject: MyObject by lazy { createExpensiveObject() }Correct
- c.private lateinit var myObject: MyObject
- d.private var myObject: MyObject? = null
Why? this is the answer
`val by lazy` is ideal for expensive, immutable properties because it defers creation until first access and caches the result. `lateinit var` is incorrect because the property is immutable and is meant for when an external framework provides the value, not for deferred computation.
Just read this? Test yourself on what you have been reading.
Read the original → kotlinlang.org
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on kotlin — each one lists the topics its interview covers.
See open roles