I am in the process of learning Kotlin, and reading about the lateinit
keyword makes me doubt its usefulness. Consider this code:
var testString: String? = null
lateinit var lateTestString: String
fun print() {
print(testString?.length)
print(lateTestString.length)
}
Here the only difference in getting the length of the string is by checking if it is null or not by using the ?.
operator. Is using the lateinit
a shortcut for not having to add that extra question mark when accessing properties or invoking methods? Just by that fact I think it is more worth having to add that extra question mark than getting an exception when accessing the lateinit
one.
More research showed me that lateinit
is good for injections and/or unit tests where the variable has not been initialized yet, but it will be. However, is it not worth having that extra ?.
instead of just .
to not risk an exception?
When To Use Lateinit. Use Lateinit : to initialize a variable late. when you are sure about initializing a variable before using it.
The lateinit keyword is used for late initialization of variables.
Lazy initialization is one of the property Delegate-s, while late initialization requires the use of a language keyword. Lazy initialization applies only to val, and late initialization applies only to var fields. We can have a lazy field of a primitive type, but lateinit applies only to reference types.
The lateinit initialization can save you from repetitive null checks that you might need when initializing properties as nullable types. This feature of lateinit properties doesn't support the nullable type.
lateinit
keyword exists to enable one specific scenario: when your field can't be null, but you also can't initialize it in the constructor or with a constant value. It is on you to make sure that you initialize the value before using it. If you don't, you get a special exception with clear meaning.
The difference between lateinit usage and "normal" nullable field with ?.
is that the latter conveys a wrong message about the code: "this thing can sometimes be null". When, in fact, it can't. It is just initialized later than usual (with dependency injection instead of constructor, for example).
Is using the
lateinit
a shortcut for not having to add that extra question mark
Actually it's much closer to a shortcut for !!
. I use it a lot in my code, for the reasons I'll try to describe.
Those two !!
have been chosen deliberately to attract attention to places in the code where you "take a bet against the type system", so to speak. When used at proper places, that's exactly what you want, but what about all those vars in real-life projects which are effectively non-null, just the type system is too weak to prove it? I'd hate to see the proliferation of !!
all around my codebase when I can easily ascertain they are initialized. This noise would weaken the strong signal that !!
sends.
When you see a lateinit var
in the code, you know you just have to look up whatever initialization method the surrounding context specifies, to convince yourself that everything's fine. It is very easy to check it's used correctly and I've never seen a bug stemming from it.
It is actually very pleasing to see the Kotlin designers putting the concerns of the real-life developer above strict type formalisms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With