The Delegates.notNull function and lateinit

Think of a situation where you need to declare a property at the class level, but you don't have the initial value for the variable there. You'll get the value at some later point, but before the property is actually used, and you're confident that the property will get initialised before using and it'll not be null. But, as per Kotlin syntax, you must initialize a property at the time of initializing. The quick fix is to declare it as a nullable var property, and assign a default null value. But as we mentioned earlier, since you are confident that the variable will not be null while using it, you are not willing to declare it as nullable.

Delegates.notNull is here to save you in this scenario. Have a look at the following program:

var notNullStr:String by Delegates.notNull<String>() 
 
fun main(args: Array<String>) { 
    notNullStr = "Initial value" 
    println(notNullStr) 
} 

Focus on the first line—var notNullStr:String by Delegates.notNull<String>(), we declared a non-null String var property, but we didn't initialize it. Instead, we wrote by Delegates.notNull<String>(), but what does it mean? Let us inspect. The by operator is a reserved keyword in Kotlin, to be used with delegates. The by operator works with two operands, on the left-hand side of by will be the property/class that needs to be delegated, and on the right-hand side will be the delegate.

The delegate—Delegates.notNull allows you to temporarily go without initializing the property. It must be initialized before it is used (as we did on the very first line of the main method), otherwise it'll throw an exception.

So, let's modify the program by adding another property, which we will not initialize before using it, and see what happens:

var notNullStr:String by Delegates.notNull<String>() 
var notInit:String by Delegates.notNull<String>() 
 
fun main(args: Array<String>) { 
    notNullStr = "Initial value" 
    println(notNullStr) 
    println(notInit) 
} 

The output looks like the following:

So, the notInit property caused the exception—Property notInit should be initialized before get.

But doesn't the variable declaration—by Delegates.notNull() sound awkward? The Kotlin team also thought the same way. That's why from Kotlin 1.1 they added a simple keyword—lateinit, to achieve the same objective. As it simply states about late initialization, it should be simply lateinit.

So, let's modify the last program by replacing by Delegates.notNull() with lateinit. The following is the modified program:

lateinit var notNullStr1:String 
lateinit var notInit1:String 
 
fun main(args: Array<String>) { 
    notNullStr1 = "Initial value" 
    println(notNullStr1) 
    println(notInit1) 
} 

In this program, we had to rename the variables, as you can't have two top-level (package-level variable, without any class/function) variables of the same name. Except variable names, the only thing that changed is we added lateinit, instead of by Delegates.notNull().

So, now let's have a look at the following output to identify if there's any change:

The output is also identical, except it slightly changes the error message. It now says, lateinit property notInit1 has not been initialized.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.70.247