Null safety can be broken in super class constructors

This code throws a NullPointerException but is accepted by the compiler:

data class Foo(val value: String)

abstract class A {
    abstract var foo: Foo

    init {
        println(foo.value)
    }
}

class B : A() {
    override var foo: Foo = Foo("Hello, World!")
}

fun main(args: Array<String>) {
    var b = B()
    println(b.foo.value)
}

As foo is not nullable I expect it not to be null when the constructor is called.
But A’s constructor is called before B’s and thus foo has is not initialized when A’s constructor is called.
And the null safety is broken.

This code is broken because you call virtual method (getter of foo) from constructor. It’s old issue of program languages, for example Invoking virtual method in constructor: difference between Java and C++ - Stack Overflow

Ok. Thanks.
Like you said the code is broken so shouldn’t the compiler give a warning or an error?

Since

 abstract var foo:Foo

is really the equivalent of this in Java:

abstract Foo getFoo();

The code may not necessarily be broken it depends on the subclass implementation. If you declared a custom getter in the subclass that just returned a constant the code would have ran fine. So there is no reason to exclude it at compile time, but it is a known gotcha that applies to Java and Kotlin equally.

For what it’s worth, I agree it’s broken and the compiler should give a warning (an error?) when using an open method or field from a constructor.

The same situation occurs in Java and it generates no warning. In many cases such access is perfectly valid and not an issue. I see no point in making people deal with warnings that may not be valid.

It’s not implemented for Kotlin yet, but for Java there is an inspection in IntelliJ IDEA warning when virtual methods are called within the constructor. I think it is only a matter of time until this would be implemented for Kotlin.

1 Like