Explain lateinit var versus val by lazy in Android

Tests deferred initialization and lifecycle coupling. Great answers contrast lateinit var's imperative assignment with lazy's first-access delegation, mapping lateinit to injected Activity fields and lazy to expensive computed objects.
What's really being asked
Whether you understand the mechanical and semantic differences between two Kotlin deferred-initialization patterns, and more importantly whether you can match each pattern to the right Android lifecycle moment. Interviewers care about mutability guarantees, null safety, thread-safety defaults, and the performance implications of initialization timing.
A GOOD ANSWER COVERS four things in order. First, the mechanical split: lateinit var is a mutable non-nullable property that remains uninitialized until you assign it imperatively, and it can only be used with reference types, never primitives. Second, lazy is a delegate that runs a lambda on first access, caches the result, and returns an immutable val; under the hood it uses a synchronized lazy implementation by default, so it is thread-safe but carries a small locking cost. Third, the Android scenario for lateinit: injected dependencies like a ViewModel or Repository, or a view reference obtained via findViewById, where the object is created by a framework callback such as onCreate or onViewCreated and must be reassigned if the component is recreated. Fourth, the Android scenario for lazy: expensive initialization that might not happen on every code path, such as formatting a large dataset, building a RecyclerView adapter, or computing a complex bitmap, especially when the property may never be accessed during a particular user session.
The mistakes people make
Saying lateinit works with val or with primitive types like Int; it requires var and a reference type. Claiming lazy is just syntax sugar for a nullable var with a custom getter, which misses the thread-safety and caching contract. Recommending lazy for view bindings inside an Activity without mentioning that the backing fragment or activity lifecycle might end before the lazy block runs, or conversely using lateinit for a one-time expensive computation that could safely be deferred. Another red flag is never mentioning the isInitialized check for lateinit, which is critical for defensive code in tests or conditional teardown.
What usually comes next
How would you test a class that uses lateinit properties without hitting UninitializedPropertyAccessException? When would you switch lazy from SYNCHRONIZED to PUBLICATION or NONE, and what are the risks? Can you use lateinit with a custom delegate? How does by lazy interact with memory leaks if it captures an Activity context?
A concrete example
In a Fragment, lateinit var is appropriate for a ViewModel obtained via ViewModelProvider inside onViewCreated, because the property must be mutable if the fragment is recreated and reassigned during a new lifecycle. By contrast, val dateFormatter by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) } is better inside the same fragment because the formatter is expensive to create, may not be used if the user never opens the date section, and should be immutable once built.
Interview question
In an Activity, a property holds a ViewModel obtained via ViewModelProvider in onCreate. Why is lateinit var more suitable than val by lazy?
- a.lateinit var works with primitive types and immutable declarations
- b.lateinit var is thread-safe by default while lazy is not
- c.lateinit var allows imperative assignment and can be reassigned if the Activity is recreatedCorrect
- d.lateinit var defers initialization until first access and caches the result
Why? this is the answer
lateinit var is designed for mutable properties assigned imperatively in lifecycle callbacks like onCreate and can be reassigned when the Activity is recreated, whereas val by lazy is immutable and self-initializing. Option D is tempting but wrong because it describes lazy's first-access caching behavior, not lateinit's imperative assignment model.
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