lateinit vs lazy in Kotlin


Both lateinit and lazy are features in Kotlin used to delay the initialization of properties, but they serve different purposes and have different characteristics. Let’s discuss each:

ateinit:

  1. Purpose:
    • lateinit is used to declare non-null properties that will be initialized later, typically before their first usage. It is mainly used for properties that cannot be initialized at the time of object creation, such as properties that are initialized in a lifecycle method or in a dependency injection scenario.
  2. Characteristics:
    • The property must be declared as var (mutable).
    • The property must be of a non-null type, and you must guarantee that it will be initialized before the first usage. Otherwise, it will throw a LateinitPropertyAccessException.
    • It cannot be used for primitive types like Int, Boolean, etc., as they cannot be null. It’s primarily used for objects and nullable types.
    • It does not perform lazy initialization; the property must be initialized manually before accessing it.
  3. Example:
class Example {
    lateinit var name: String

    fun initialize() {
        name = "John"
    }

    fun printName() {
        if (::name.isInitialized) {
            println(name)
        } else {
            println("Name is not initialized")
        }
    }
}

lazy:

  1. Purpose:
    • lazy is used to declare properties whose values are computed lazily, meaning they are calculated only when accessed for the first time and then cached for subsequent accesses. It’s useful for properties that are computationally expensive or require initialization only on demand.
  2. Characteristics:
    • The property must be declared using the lazy function delegate.
    • The property can be val (immutable).
    • The lambda passed to lazy is executed only upon the first access to the property.
    • The property is thread-safe by default.
    • The lazy delegate creates a Lazy<T> instance, which holds the lambda and caches its result after the first evaluation.
    • The property’s type is inferred from the lambda expression.
  3. Example:
class Example {
    val name: String by lazy {
        println("Computing name...")
        "John"
    }

    fun printName() {
        println(name) // Accessing the property for the first time
        println(name) // Accessing the property again (value is cached)
    }
}

In summary, lateinit is used for properties that are guaranteed to be initialized before their first usage but need to delay initialization, while lazy is used for properties whose initialization can be deferred until they are accessed for the first time.

Leave a Reply