Advantage of lateinit over null initialization in java?

The idea is to make compiler aware that the property is non-nullable though it will be initialized later. That would reduce null-checks on this property in the receiver code.

class Foo {
    lateinit var prop: String
}

class Bar {
    var prop: String? = null
}

fun consumeNotNull(arg: String) {
    println(arg)
}

fun main() {
    val foo = Foo()
    consumeNotNull(foo.prop) // OK

    val bar = Bar()
    consumeNotNull(bar.prop) // Error: Type mismatch: inferred type is String? but String was expected
    consumeNotNull(bar.prop!!) // OK
}

Imagine that bar.prop is referred to in N places. Then in each place you have to "scream" at it (bar.prop!!) to make compiler happy. lateinit mechanism lets you to to avoid that and be more "quiet" :) (and keep your code cleaner)

Of course, if Foo::prop isn't initialized by the moment of using it in runtime, you will get exception:

UninitializedPropertyAccessException: lateinit property prop has not been initialized

but in compare to NullPointerException it's bit more descriptive.


One another use of a lateinit variable is that once it is initialized you can never make it uninitialized, "So one check will make it sure that it is never gotta be a null or changed by any other Thread".

class Foo {
    lateinit var prop: String
}

class Bar {
    var prop: String? = null
}

fun main() {
    val foo = Foo()
    foo.prop = "Hello"
    // You can never make it uninitialized now, you can only change it.
    // A single isInitialized is ok. (Rather than checking everytime, because it can be null again)

    val bar = Bar()
    bar.prop = "String"
    println(bar.prop!!)
    bar.prop = null
    println(bar.prop!!) // KotlinNullPointerException, check everytime you use it with ?. operator
    // Call when not null: bar.prop?.let { println(it) }
}

In addition to Nikolai Shevchenko's answer: even inside the class I'd consider isInitialized a likely indicator that a nullable property can be more useful.

The primary use-case for lateinit is when you can't initialize a property in the constructor but can guarantee that it's initialized "early enough" in some sense that most uses won't need an isInitialized check. E.g. because some framework calls a method initializing it immediately after construction.

In fact, originally there was no isInitialized; it only appeared in Kotlin 1.2, and lateinit was already in 1.0 (I believe).

Tags:

Java

Kotlin