ProgrammingAndroid Developer

How does the late-initialized property ('lateinit var') work in Kotlin, how does it differ from nullable properties, and in what situations should it be used?

Pass interviews with Hintsage AI assistant

Answer

Background

Kotlin focuses on type safety and avoiding null pointers, but often there is a need for delayed initialization of variables, for instance, when using dependency injection or in Android Activities. For this purpose, the lateinit modifier has been added.

Problem

Regular properties require mandatory initialization or must be nullable, which is inconvenient when late but guaranteed initialization is assured. Using a nullable type complicates the code and requires additional null checks.

Solution

Lateinit allows the creation of a property that is not initialized immediately but promises the compiler that it will be initialized before its first use. Initialization can be done later, not just in the constructor.

class UserViewModel { lateinit var repository: UserRepository fun onCreate() { repository = UserRepository() } fun getData() = repository.load() }

Key features:

  • Allows not using null while deferring initialization
  • Throws UninitializedPropertyAccessException when accessing an uninitialized lateinit property
  • Only for var and not for primitive types (Int, Double etc.)

Trick Questions

Can lateinit be used for val properties?

No. Lateinit works only with var, as val must be initialized once immediately or through a getter.

Does lateinit work with types like Int, Boolean, Double, and other primitives?

No. Only with object reference types. For primitives, use nullable types.

What happens if you access a lateinit property before initialization?

Kotlin will throw UninitializedPropertyAccessException:

lateinit var foo: String println(foo) // Exception

Common Mistakes and Anti-patterns

  • Forgot to initialize a lateinit property — the application will crash
  • Using it where nullable semantics with isInitialized check is needed
  • Applying it for primitive types and val

Real-life Example

Negative Case

A developer declared lateinit var item: String, did not initialize it before the first call to the getItem method. Result: the application crashes.

Pros:

  • Eliminates nullability if everything is initialized correctly

Cons:

  • Risk of mixing up the lifecycle and getting a runtime exception

Positive Case

Android Activity: lateinit var presenter, initialized in onCreate. Using presenter in all lifecycle methods is safe: no nullability needed.

Pros:

  • Improves readability, avoids unnecessary checks
  • Guarantees mandatory initialization

Cons:

  • The need to explicitly follow the order of initialization calls