Normally, properties declared as having a non-null type must be initialized by the constructor. However, it is often the case that doing so is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In these cases, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class. This is precisely the situation lateinit
was designed to solve.
While it may seem very ad-hoc to include this as a language feature, it reflects the pragmatic realization of the Kotlin team that every single modern application larger than a small private project uses some sort of unit test framework & dependency-injection framework, the majority of which are based on Java. This means that every single modern application would suffer from this problem and Kotlin would not be compatible with frameworks such as Spring, severely decreasing Kotlin adoption and Java interop. Adding lateinit
as a feature allows us to keep the good stuff in Kotlin, while still being realistic about the real world.
When using Spring, you will most often use lateinit
when injecting a dependency differently than via constructor injection:
//sampleStart @Component class SomeService(private val otherService: OtherService) @Component class OtherService { // SomeService cannot be injected via // constructor, since it needs a reference // to OtherService, which is a dependency loop // This won't work, because every property // must be initialized either directly or // in the constructor // @Autowired // private val someService: SomeService // This works, but we have to use var @Autowired private lateinit var someService: SomeService } //sampleEnd
However, be wary of the above code β itβs prone to failure, and may or may not work on your system.
For more technical information aboutΒ lateinit
,Β take a look at the docs.