-3

I have been using both of them, both of them provide safety for NullPointerException but the lateinit can cause UnInitializedPropetyException, So which of these two is safer. What is the best use case for each of them, when the lateinit best fits and when lazy best fits?

The point I am trying to make is based on

  1. Safety //lateinit saves from NPE but it can throw UnInitializedPropetyException
  2. Optimality

Is not it better to go for lazy, when one does not really need mutable property?

What is the usefulness of lateinit?

when lateinit var abc:Def can give UnInitializedPropetyException and var abc:Def?=null can give NPE, in both cases we have mutability and exception.

rahat
  • 1,840
  • 11
  • 24
  • 6
    Does this answer your question? [Kotlin - Property initialization using "by lazy" vs. "lateinit"](https://stackoverflow.com/questions/36623177/kotlin-property-initialization-using-by-lazy-vs-lateinit) – Uuu Uuu Jan 21 '21 at 04:26

4 Answers4

4

They have two different purposes:

  1. by lazy is for initialising something only if it is accessed runtime at some point. Consider a costly/resource intensive component or initialisation. If this component is used only in certain cases, by lazy can help with avoiding these costly initialisations
  2. lateinit is more of a convenience method if you can't initialise something right away. For ex. in android if you want to save out a reference to one of your views, you can only initialise them in your onCreateView/onViewCreated. Unfortunately lateinit works with vars only, so it doesn't enforce immutability, so use it with caution :)

Update: Both with lateinit and with the nullability pattern you get mutability & unsafety, so in this sense they are not so different.

But lateinit is a lot more verbose in the sense that you know if something goes wrong it's an initialisation problem (or it should be). The nullability pattern is okay for more general problems, for ex: if you plan on clearing/resetting a component

Róbert Nagy
  • 6,720
  • 26
  • 45
  • 1
    (+1) with one tiny quibble - it's not so much a "convenience" but a necessity given the combination of (a) how Kotlin handles `val` assignments, and (b) the requirement for deferred initialization that some libraries/frameworks impose (such as Android, as you pointed out) – homerman Jan 21 '21 at 06:47
  • @homerman agreed, I was referring to the convenience of using it instead of nullables – Róbert Nagy Jan 21 '21 at 06:57
  • @NagyRobi, Please enlighten me based on the added information to the quesiton – rahat Jan 21 '21 at 07:07
1

lazy is safest because you need assign a value to it first and don't worry about initial state. Beside, about the resource, when first use lazy object, it is initialized. About performance, the result is saved in memory when you call get() first and then each get() call give result from memory.

About best case use them late init and lazy

  • late init use in case you not sure about the way which object is initialized and mutability
  • lazy use in case, you want only instance object exist in class scope and immutability
Tungken
  • 1,917
  • 1
  • 15
  • 18
0
  • When to use which one?

    lateinit can only be used with var (mutable)properties whereas lazy can only be used for val (immutable)properties. lateinit don’t work with primitive type. While using Singleton Pattern (Object Declaration in Kotlin) we should use lazy, as it will be initialized upon first use. In lateinit the type of the property must be non-null. lateinit can only be used when the property does not have a custom getter or setter. In lateinit var, it depends on the user to initialize the property properly in multi-threaded environments. Initialization by lazy { … } is thread-safe by default and make sure initialization is done at most once.

      var — Declared as mutable
      val — Read-only (immutable)
    
      val someText: String by lazy { "Variable is lazy initialized" }
      fun doPrintSomeText() {
      println("Length is  " + someText.length) // someText will be initialized here
      }
    
      lateinit var someText: String // initialize laterfun doPrintSomeText() {
      someText = "Variable is lateinit" // initialize 
      println("Length is  " + someText.length)
      }
    
Sandeep Pareek
  • 1,636
  • 19
  • 21
0

You can check if lateinit var is initialized or not before using it

lateinit var foo: Foo
if(::foo.isInitialized) {
    // foo is initialized. Go Ahead
}

When you know the var will be needed but not at the time of class loading, then You can declare it with lateinit. This means You will initialize it as per your need.

By lazy indicates that the variable is going to be initialized at the time of its first usage. And If you do not need to use that variable then it will not initialize at all.

And this will not result in NPE in any way.

In short, If we declare it as lateinit, then its tottally our duty as a developer to initialize it before using it

Bhargav Thanki
  • 4,924
  • 2
  • 37
  • 43