Kotlin DISCUSSION

Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

Started by nishenmahendran Kotlin lateinitby lazyproperty initializationUninitializedPropertyAccessExceptionlazy thread safety
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

nishenmahendran Kotlin Forum
#1

My class has a property that cannot be set in the constructor: a serial port handle that is opened in start(), and a lookup table that is expensive to compute and not always needed. I have seen both lateinit var port: SerialPort and val table by lazy { buildTable() } used for this kind of thing.

What are the actual differences and restrictions of the two, and what happens if the property is read too early?

Community replies 5

Re: Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

#2

They solve different problems. lateinit var is a promise that some other code will assign the property before it is read. The initialisation happens from outside, at a time you choose, and the property can be reassigned later. val x by lazy { ... } carries its own initialiser: the lambda runs on first access, the result is stored, and every later read returns the stored value. It can never be assigned again.

For your case, the port opened in start() is a lateinit candidate and the lookup table is exactly what lazy is for.

Re: Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

#3

Restrictions of lateinit: it must be a var, the type must be non-null, and it cannot be a primitive type such as Int, Long, Double or Boolean. Reading it before assignment throws UninitializedPropertyAccessException, which names the property, so the failure is at least clear.

You can test the state with a property reference: if (::port.isInitialized) port.close(). That is handy in cleanup code, but if you find yourself checking it in many places, a nullable var port: SerialPort? = null describes the situation more honestly.

Re: Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

#4

lazy is thread-safe by default. The default mode, LazyThreadSafetyMode.SYNCHRONIZED, takes a lock so the initialiser runs at most once even when several threads hit the first access together. If the property is only ever touched from one thread, lazy(LazyThreadSafetyMode.NONE) { ... } skips the locking. PUBLICATION allows the initialiser to run more than once concurrently but keeps the first result.

lateinit has no synchronisation of any kind; it is a plain field.

Re: Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

#5

Two pitfalls with lazy. If the initialiser throws, nothing is stored and the next access runs it again, so a failing initialiser can fail repeatedly. And the value is cached for the lifetime of the owning object: if it depends on something that changes later, the cached result goes stale and there is no way to reset it.

On Android this shows up with views in a Fragment, where the view hierarchy can be destroyed and recreated while the Fragment object survives; a lazily cached view reference then points at the old view.

Re: Kotlin lateinit var or by lazy: which should I use for a property initialised after construction?

#6

For the primitive case that lateinit rejects, the options are a nullable type, a sensible default value, or var baud: Int by Delegates.notNull<Int>() from kotlin.properties, which throws IllegalStateException if read before being set.

As a rule of thumb: constructor parameter if you can; by lazy when the object can compute the value itself on demand; lateinit when a framework or a lifecycle method supplies it; nullable when "not set yet" is a normal state the code has to handle.

TEP COMMUNITY