Learn Kotlin — lateinit vs lazy

There are many great features available in Kotlin, we can take advantage of all these features to write a better application in Kotlin. Among all those features, lateinit
and lazy
are important property initialization feature. We must know when to use which property initialization.
Welcome to MindOrks! In this blog, we are going to learn what lateinit
and lazy
keywords are used for in Kotlin, and what is the difference between these two?
Lateinit keyword
There are many cases when you need to create a variable but you don't want to initialize it at the time of declaration/creation of the variable because you are sure that the variable will be initialized before its access/usage.
One way of achieving this is by making the variable nullable like this:
private var courseId: String? = null
But what if you don't want to make it nullable? Here comes the use of the lateinit
keyword.
The lateinit
keyword is used for late initialization of variables.
Here is an example of lateinit:
private lateinit var courseName: String
// demo function to get course name using the courseId
fun fetchCourseName(courseId: String) {
courseName = courseRepository.getCourseName(courseId)
// this is an example, you can add other suff according to your usecase
}
You should be very sure that your lateinit
variable will be initialized before accessing it otherwise you will get:
UninitializedPropertyAccessException: lateinit property courseName has not been initialized
If you are not sure about the nullability of your lateinit
variable then you can add a check to check if the lateinit
variable has been initialized or not by using isInitialized
:
if(this::courseName.isInitialized) {
// access courseName
} else {
// some default value
}
NOTE: To use alateinit
variable, your variable should usevar
and NOTval
. Lateinit is allowed for non-primitive data types only and the variable can't be of null type. Also, lateinit variable can be declared either inside the class or it can be a top-level property.
Usage of lateinit
- For late initialization of variables.
- For injecting an object using Dagger.
Now, let's learn about the lazy
keyword.
Lazy keyword
There are certain classes whose object initialization is very heavy and so much time taking that it results in the delay of the whole class creation process.
For example, let's say you have a class named HeavyClass
and you need an object of this HeavyClass
in some other class named SomeClass
:
class SomeClass {
private val heavyObject: HeavyClass = HeavyClass()
}
Here, we are creating a heavy object and this will result in slow or delayed creation of the SomeClass
. There may be cases where you may not need the HeavyClass
object. So, in this case, the lazy
keyword can help you:
class SomeClass {
private val heavyObject: HeavyClass by lazy {
HeavyClass()
}
}
Now, the benefit of using lazy
is that the object will be created only when it is called otherwise it will not be created.
The other benefit of using lazy is that once the object is initialized, you will use the same object again when called.
For example:
class SomeClass {
private val heavyObject: HeavyClass by lazy {
println("Heavy Object initialised")
HeavyClass()
}
fun accessObject() {
println(heavyObject)
}
}
fun main(args: Array<String>) {
val someClass = SomeClass()
println("SomeClass initialised")
someClass.accessObject()
someClass.accessObject()
}
The output of the above code is:
SomeClass initialised
Heavy Object initialised
HeavyClass@2a84aee7
HeavyClass@2a84aee7
In the above code, you can see that the object of the HeavyClass
is created only when it is accessed and also the same object is there all over the main()
function.
Lazy is mainly used when you want to access some read-only property because the same object is accessed throughout.
That's it for this blog. If you want to learn about lateinit and lazy by watching from video, you can watch our video from MindOrks YouTube channel.
Happy Learning :)
Team MindOrks!