# Why can't one use lateinit with nullable types?

**URL:** <https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992>\
**Category:** Language Design\
**Created:** [November 22, 2020, 8:45pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992 "2020-11-22T20:45:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![oakkitten](https://avatars.discourse-cdn.com/v4/letter/o/7cd45c/32.png) [@oakkitten](https://discuss.kotlinlang.org/u/oakkitten)\
**Post date:** [November 22, 2020, 8:45pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/1 "2020-11-22T20:45:40Z")

</div>

If you write

```kotlin
class Foo {
    lateinit var foo: String?
}

```

you’ll get

> ‘lateinit’ modifier is not allowed on properties of nullable types

Is there a particular reason this is disallowed?

In many cases `null` is a correct value for a variable, and so can not signify an uninitialized state. So I think it would be nice if I could use `lateinit` with nullable types. For instance, consider this kind of code:

```kotlin
class Foo {
    var foo: String? = null

    fun initFoo() {
        foo = if (something) "foo" else null
    }

    fun useFoo() {
        if (foo == null) bar() else baz()
    }
}

```

It this example it would be incorrect to call `useFoo()` before `initFoo()`. But this _can_ happen, and in this case `useFoo()` will call `bar()` instead of crashing. And what if `bar()` reelects Trump or something? So to avoid that, you have to use a bogus object to signify a “nullish” value, or use an “initialized” flag…

I understand that [internally](https://medium.com/@kiitvishal89/deep-dive-into-whats-inside-kotlin-lateinit-e6570cb9a220) `null` represents an uninitialized `lateinit` state; but can’t a different kind of marker be used instead?

---

<div class="post-metadata">

**Author:** ![nickallendev](https://avatars.discourse-cdn.com/v4/letter/n/cdc98d/32.png) [@nickallendev](https://discuss.kotlinlang.org/u/nickallendev)\
**Post date:** [November 23, 2020, 6:35am UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/3 "2020-11-23T06:35:01Z")

</div>

> [@oakkitten](#):
>
> can’t a different kind of marker be used instead?

JVM guarantees the types of everything (just not nullity), so Kotlin can’t just assign some random token object under the covers. A null value for non-null types is the only case where Kotlin can assign a value that is not of the correct Kotlin type but is acceptable to the JVM.

Honestly, I view the ability to check if `lateinit vars` are initialized as only marginally valuable in general and have never used it personally.

`lateinit` is super helpful in cases where real initialization happens after construction and its impossible to provide any value at all of the right type before the initialization method is called.

On Android, I can’t have an Activity member variable of type View without `lateinit`. It’s impossible to create a `View` without the `Context` that is provided to `onCreate`. Many of the vars I might use on Android fall in this category. I don’t need a special uninitialized value to check for, I just can’t create any value at all to use as a placeholder until `onCreate` is called.

---

<div class="post-metadata">

**Author:** ![oakkitten](https://avatars.discourse-cdn.com/v4/letter/o/7cd45c/32.png) [@oakkitten](https://discuss.kotlinlang.org/u/oakkitten)\
**Post date:** [November 23, 2020, 4:10pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/4 "2020-11-23T16:10:25Z")

</div>

> [@nickallendev](#):
>
> JVM guarantees the types of everything (just not nullity), so Kotlin can’t just assign some random token object under the covers.

I’m not quite sure if this is right, for instance here’s a complete and runnable example of a property similar to `Delegates.notNull()` but nullable—and it works fine in JVM too:

```kotlin
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import java.lang.Exception

object Missing

private class Property<T> : ReadWriteProperty<Any?, T> {
    private var value: T = Missing as T

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        if (value === Missing) {
            throw IllegalStateException("Property ${property.name} should be initialized before get.")
        } else {
            return value
        }
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        this.value = value
    }
}

object Test {
    var foo by Property<String?>()
}

fun main() {
    try {
        Test.foo
    } catch (e: IllegalStateException) {
        println("error while getting foo: $e")
        println("setting foo to null")
        Test.foo = null
    }

    if (Test.foo == null) {
        println("foo is null, setting to 'foo'")
        Test.foo = "foo"
    }

    println("foo is '${Test.foo}'")
}

```

This prints:

> error while getting foo: java.lang.IllegalStateException: Property foo should be initialized before get.  
> setting foo to null  
> foo is null, setting to ‘foo’  
> foo is ‘foo’

> [@nickallendev](#):
>
> `lateinit vars` are initialized as only marginally valuable

I agree that their use cases are rare, perhaps very rare, but IMO sometimes you do need them and the alternatives are just too complex and ugly

---

<div class="post-metadata">

**Author:** ![Varia](https://avatars.discourse-cdn.com/v4/letter/v/b9e5f3/32.png) [@Varia](https://discuss.kotlinlang.org/u/Varia)\
**Post date:** [November 23, 2020, 4:38pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/5 "2020-11-23T16:38:56Z")

</div>

That only works because the type of your lateinit property is an unbounded type parameter, which means it gets erased to `Object` when compiled. If you were to try the same with any other type, you would get either a compiler error, or a ClassCastException during construction at runtime.

---

<div class="post-metadata">

**Author:** ![oakkitten](https://avatars.discourse-cdn.com/v4/letter/o/7cd45c/32.png) [@oakkitten](https://discuss.kotlinlang.org/u/oakkitten)\
**Post date:** [November 23, 2020, 4:48pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/6 "2020-11-23T16:48:00Z")

</div>

Are you saying that this kind of trick would be impossible to use with `lateinit`? I don’t know the internals of JVM. I assumed that if I can make this work using a simple cast, one could make it work even better via custom bytecode

---

<div class="post-metadata">

**Author:** ![Varia](https://avatars.discourse-cdn.com/v4/letter/v/b9e5f3/32.png) [@Varia](https://discuss.kotlinlang.org/u/Varia)\
**Post date:** [November 23, 2020, 5:03pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/7 "2020-11-23T17:03:31Z")

</div>

JVM performs type checks at runtime, which makes it impossible to either assign a value to a field of incompatible type, or call a method with parameters of incompatible types. If you were to write bytecode by hand that tries to do so, then the JVM would throw an error, either during bytecode verification or when executing the violating method.

---

<div class="post-metadata">

**Author:** ![oakkitten](https://avatars.discourse-cdn.com/v4/letter/o/7cd45c/32.png) [@oakkitten](https://discuss.kotlinlang.org/u/oakkitten)\
**Post date:** [November 23, 2020, 5:08pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/8 "2020-11-23T17:08:40Z")

</div>

Well, if type erasure is the only trick that can do it, why not use it? It seems that it works well, even in my silly example

---

<div class="post-metadata">

**Author:** ![Varia](https://avatars.discourse-cdn.com/v4/letter/v/b9e5f3/32.png) [@Varia](https://discuss.kotlinlang.org/u/Varia)\
**Post date:** [November 23, 2020, 5:22pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/9 "2020-11-23T17:22:01Z")

</div>

In that case, every `lateinit` property with a nullable type (if you were to also include non-nullable properties, it would be a breaking change) would have to compiled to a field of type `Object`. This would affect a lot of libraries that use reflection to check the type of the field. Since field injection is a rather significant use case for lateinit properties, this is a quite significant limitation.

---

<div class="post-metadata">

**Author:** ![oakkitten](https://avatars.discourse-cdn.com/v4/letter/o/7cd45c/32.png) [@oakkitten](https://discuss.kotlinlang.org/u/oakkitten)\
**Post date:** [November 23, 2020, 5:48pm UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/10 "2020-11-23T17:48:11Z")

</div>

I see. While this limitation is, in fact, limiting, I’m not sure if anything is gained by prohibiting nullable `lateinit`:

- field injection libraries can simply refuse to work with nullable fields
- it wouldn’t break any existing code since nullable lateinit vars currently do not exist
- it sounds like the limiting factor here is JVM and while it is big it’s not the whole Kotlin

…well, apart from not having to write the code

---

<div class="post-metadata">

**Author:** ![mrbenjoi](https://avatars.discourse-cdn.com/v4/letter/m/82dd89/32.png) [@mrbenjoi](https://discuss.kotlinlang.org/u/mrbenjoi)\
**Post date:** [February 4, 2024, 11:50am UTC](https://discuss.kotlinlang.org/t/why-cant-one-use-lateinit-with-nullable-types/19992/11 "2024-02-04T11:50:57Z")

</div>

This topic has rested for a while already. I still like to suggest the following solution as an alternative to nullable lateinits.

How about making a helper class that does the init check on a nullable type on each read and then use it as a delegate:

```kotlin
class NullableLateInit<T> {
    private var initialized = false
    private var value: T? = null

    operator fun getValue(o: Any, prop: KProperty<*>): T? {
        if (!initialized) throw Exception("Access before init.")
        return value
    }

    operator fun setValue(o: Any, prop: KProperty<*>, value: T?) {
        this.value = value
        initialized = true
    }
}

fun <T> lateInit(): NullableLateInit<T> {
    return NullableLateInit()
}

class Foo {
    // Use like this...
    var foo by lateInit<String?>()
    var bar: String? by lateInit()
}

```

This solution can further be refined for thread safety and performance requirements.
