Do we need to initialize nullable fields in kotlin?

Viewed 9439

I have recently reviewed some kotlin codes, All nullable field initialized as null.

What is the difference between val x : String? = null and val x : String?

Should we initialize the nullable fields as null?

3 Answers

Everything, even nullable variables and primitives, need to be initialized in Kotlin. You can, as tynn mentioned, mark them as abstract if you require overriding. If you have an interface, however, you don't have to initialize them. This won't compile:

class Whatever {
    private var x: String? 
}

but this will:

interface IWhatever {
    protected var x: String?
}

This too:

abstract class Whatever {
    protected abstract var x: String?
}

If it's declared in a method, you don't have to initialize it directly, as long as it's initialized before it's accessed. This is the exactly same as in Java, if you're familiar with it.

If you don't initialize it in the constructor, you need to use lateinit. Or, if you have a val, you can override get:

val something: String?
    get() = "Some fallback. This doesn't need initialization because the getter is overridden, but if you use a different field here, you naturally need to initialize that"

As I opened with, even nullable variables need to be initialized. This is the way Kotlin is designed, and there's no way around that. So yes, you need to explicitly initialize the String as null, if you don't initialize it with something else right away.

A property must be initialized. Therefore you have to do the initialization var x : String? = null. Not assigning a value is only the declaration of the property and thus you'd have to make it abstract abstract val x : String?.

Alternatively you can use lateinit, also on non-nullable types. But this has the effect, that it's not null, but uninitialized lateinit var x : String.

val x : String? will create an uninitialized variable or property, depending on where it's defined. If it's in a class (rather than a function), it creates a property, and you cannot create an uninitalized property unless it's abstract. For example take this code:

class MyClass {
    val x : String?
}

This won't compile. You'll get Property must be initialized or be abstract.

This code, however, will compile

class MyClass {
    fun test() {
        val x : String?
    }
}

However it's a bit pointless as you will not be able to refer to that variable: as soon as you do you'll get Variable 'x' must be initialized.

So yes, generally when defining a nullable member you should initialize it (e.g. with a value of null), unless it's abstract, in which case the overriding class should initialize it.

Related