Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the keyword lateinit unnecessary?

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?

like image 950
Simon Zettervall Avatar asked Jan 10 '18 13:01

Simon Zettervall


People also ask

Should we use Lateinit?

When To Use Lateinit. Use Lateinit : to initialize a variable late. when you are sure about initializing a variable before using it.

What is the Lateinit modifier for?

The lateinit keyword is used for late initialization of variables.

What is the difference between lazy and Lateinit?

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.

Can Lateinit be NULLable?

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.


2 Answers

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).

like image 82
Sergio Tulentsev Avatar answered Nov 23 '22 17:11

Sergio Tulentsev


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.

like image 31
Marko Topolnik Avatar answered Nov 23 '22 18:11

Marko Topolnik