In Kotlin, there are two different approaches for late initialization of properties: lateinit and lazy.
lateinit is a modifier applied to variables (var) that will be initialized later, usually through DI or in an initialization block. It is suitable only for non-static variables of NON-nullable types. Accessing it before initialization throws an UninitializedPropertyAccessException.
class MyClass { lateinit var data: String fun init() { data = "Hello!" } }
lazy is a special delegate applied to val properties (read-only only). The initializer expression is evaluated on the first access to the variable. It is safe for multi-threaded access by default.
val config: Config by lazy { loadConfigFromFile() }
lateinit does not work with primitive types and val.lazy does not allow re-initialization.lateinit is for variables that are guaranteed to be assigned later (for example, via a DI framework or during an Android lifecycle fragment).lazy is for lazy calculations when the value is costly to compute and may not be required.Can
lateinitbe used for properties of type Int?
Answer: No. lateinit works only with object NON-nullable types. It cannot be used for primitives and nullable types. Attempting to declare lateinit var a: Int will result in a compilation error.
Story
In an educational project, they declared a configuration variable as lateinit var config: Config?, but the compiler did not allow this — they saved time but had to figure out why it did not work as expected.
Story
In an Android application, they forgot to check for initialization of the lateinit property before calling it. This led to a crash in production — the designer tried to access the property before onCreateView. Additional checks helped.
Story
When using multi-threading, a developer applied by lazy for initializing a resource-intensive object without passing a parameter, thinking that the default delegate is not thread-safe. As a result, there were race condition issues in the release. They resolved this by passing the appropriate parameter for lazy: by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.