Properties, lazy & lateinit Quiz
KOTLIN › Language Idioms
Which property can be declared with lazy { ... }?
- A var, because lazy needs a setter to work too
- A val, since lazy is a read-only delegate only
- Only a const val, since lazy must be compile-time
- Any property, including constructor primitives, works
Answer: A val, since lazy is a read-only delegate only
lazy() returns a Lazy<T> delegate that only supplies getValue, so it can back a val (read-only). There is no setValue, so it cannot be used with var.
What happens to a const val reference after compilation?
- It calls a generated getter every time it is accessed at runtime
- It is kept in a backing field and read lazily on first access
- Its literal value is inlined directly at each usage site
- It is boxed and cached inside a companion object for reuse
Answer: Its literal value is inlined directly at each usage site
const val is a compile-time constant whose value is inlined at every reference, so no getter is called and access is essentially free.
Which declaration is INVALID for lateinit?
- lateinit var adapter: RecyclerView.Adapter
- lateinit var count: Int
- lateinit var name: String
- lateinit var listener: View.OnClickListener
Answer: lateinit var count: Int
lateinit cannot be used with primitive types like Int; it requires a non-null reference type because it relies on a null sentinel to detect the uninitialized state.
Accessing a lateinit var before it is assigned throws what?
- kotlin.UninitializedPropertyAccessException
- java.lang.NullPointerException for a missing reference
- IllegalStateException when the property is not ready
- KotlinNullPointerException for an unassigned lateinit
Answer: kotlin.UninitializedPropertyAccessException
Reading an unassigned lateinit property throws kotlin.UninitializedPropertyAccessException, a dedicated exception distinct from NPE.
Which property does NOT get a backing field generated?
- var x: Int = 0
- var score: Int = 0 with a setter that uses field
- val area: Int get() = width * height
- var name: String = "" with a default getter
Answer: val area: Int get() = width * height
A property with only a custom getter that never references field is fully computed, so the compiler generates no backing field. The others use field or default accessors, which require storage.
What is the default thread-safety mode of lazy()?
- LazyThreadSafetyMode.NONE, which skips any synchronization
- LazyThreadSafetyMode.PUBLICATION, allowing duplicate init runs
- No synchronization at all; the initializer may race freely
- LazyThreadSafetyMode.SYNCHRONIZED, with locking by default
Answer: LazyThreadSafetyMode.SYNCHRONIZED, with locking by default
Without an argument, lazy() uses SYNCHRONIZED, which locks so the initializer runs at most once even under concurrent access.
Inside a custom setter, what does the field keyword refer to?
- A recursive call back into the setter, causing another assignment
- The property's backing field that stores the value
- The KProperty metadata object for the property being accessed
- The previous value before assignment, available only as read-only
Answer: The property's backing field that stores the value
field is the special identifier for the property's backing field, available only inside accessors; assigning field = value stores the value without recursively invoking the setter.
You need a non-null Int property assigned after construction, but lateinit rejects primitives. What is the idiomatic Kotlin solution?
- Make it Int? and litter !! everywhere you later read it
- Declare it a const val and reassign it after construction
- Use by Delegates.notNull<Int>() from kotlin.properties
- Use lazy { 0 } then overwrite the cached value afterward
Answer: Use by Delegates.notNull<Int>() from kotlin.properties
Delegates.notNull() supplies a delegate that works for primitives and throws if read before assignment, filling the gap that lateinit leaves because lateinit cannot be applied to primitive types.
Where is a const val allowed to be declared?
- At top level, in an object, or in a companion object
- Inside any function body as a local compile-time constant
- As an ordinary instance member of any regular class type
- As a val parameter in a class's primary constructor
Answer: At top level, in an object, or in a companion object
const requires a value known at compile time with no per-instance storage, so it is restricted to top-level declarations, objects, or companion objects and cannot be an instance member or a local.
When is LazyThreadSafetyMode.NONE the appropriate choice for lazy()?
- When several threads must each run the initializer separately
- When you want the initializer to run again on every property read
- Only when the lazy value is nullable and may start out as null
- When access stays on one thread and you want no locking overhead
Answer: When access stays on one thread and you want no locking overhead
NONE removes all synchronization for the cheapest possible access, which is safe only when the property is touched from one thread; concurrent access under NONE is undefined behavior.
A val has a custom getter and no backing field and is read twice in a row. What is guaranteed?
- The getter runs once and caches its result like a lazy value
- The getter runs on every read, so each access can differ
- It fails to compile because a val must have backing storage
- Kotlin silently turns it into a lazy delegate behind the scenes
Answer: The getter runs on every read, so each access can differ
A computed property runs its getter on every access and caches nothing, so a val such as get() = System.currentTimeMillis() can return a fresh value each time it is read.
Given private val _items = mutableListOf<T>(); val items: List<T> get() = _items, what does external code receive when it reads items?
- A MutableList that external code can freely add to and edit
- A fresh defensive copy made every time the property is read
- A read-only List view of the same underlying mutable list
- null, since _items is private and can't be seen outside
Answer: A read-only List view of the same underlying mutable list
Callers see the List interface, which exposes no mutators, while the same underlying instance stays mutable internally; it is a view rather than a copy, so internal mutations are visible through items.
For the declaration var token: String = ""; private set, which statement is true?
- External code can read it, but only the declaring class can assign it
- Making the setter private also makes the getter private to outside code
- The property becomes read-only, even within the class that declares it
- A property with a private setter can no longer use an initializer value
Answer: External code can read it, but only the declaring class can assign it
private set narrows only the setter's visibility; the getter remains public, so outside code can read token while only the declaring class is allowed to write to it.
What is the correct way to check a lateinit property's initialization state from inside its class?
- Call name.isInitialized() directly on the property itself
- Query Delegates.isInitialized(name) from kotlin.properties
- Compare it against null, e.g. if (name != null)
- Use a property reference: this::name.isInitialized
Answer: Use a property reference: this::name.isInitialized
isInitialized is exposed only through a property reference such as this::name.isInitialized; it returns true once assigned and is available only where the property itself is accessible.