lateinit & lazy

lateinit and lazy are two ways to delay initialization: lateinit var lets you set a non-null property later by hand, while by lazy computes a val automatically on first access and caches it.

Learn lateinit & lazy in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Both avoid giving a value before you actually have one — you'll learn exactly when to reach for each.

What You'll Learn in This Lesson

1️⃣ lateinit var — Initialize Later

A lateinit var declares a non-null property with no initial value, promising you'll assign it before any read. This is common when a framework or a setup step provides the value after the object is constructed.

Reading a lateinit property before it's set throws an exception. You can check first with ::prop.isInitialized :

2️⃣ by lazy — Compute Once, On First Access

The by lazy {' '} delegate runs its block the first time the property is read, then caches the result. Later reads return the cached value without re-running the block. It's ideal for expensive values you might not even need.

3️⃣ Eager val vs lazy val

A regular val is computed eagerly — right where it's declared. A by lazy val is computed lazily — not until something reads it. Watch the print order to see exactly when each block runs.

Your turn. Fill in the ___ blank, then run and compare.

Prove that lazy computes only once: the "connecting..." line must appear a single time even though you read the value twice.

📋 Quick Reference — lateinit & lazy

Practice quiz

What does 'lateinit var' promise the compiler?

  • The value is computed automatically
  • A non-null value will be assigned before it is read
  • The property is immutable
  • The value is always null

Answer: A non-null value will be assigned before it is read. lateinit var declares a non-null property you promise to set before reading it.

What happens if you read a lateinit property before assigning it?

  • It returns null
  • It returns an empty string
  • It throws UninitializedPropertyAccessException
  • It returns zero

Answer: It throws UninitializedPropertyAccessException. Reading a lateinit property too early throws UninitializedPropertyAccessException.

How do you check whether a lateinit property has been set?

  • prop != null
  • prop.isSet()
  • ::prop.isInitialized
  • prop.exists

Answer: ::prop.isInitialized. Use the ::prop.isInitialized check to guard against reading too early.

Which of these can lateinit be applied to?

  • A val
  • An Int property
  • A var of a non-null reference type
  • A computed property

Answer: A var of a non-null reference type. lateinit works only on a var of a non-null reference type — not val or primitives.

When does a 'by lazy { }' block run?

  • The first time the property is read
  • At program startup
  • Every time it is read
  • When the object is constructed

Answer: The first time the property is read. The lazy block runs once, on first access, then caches its result.

How many times does a lazy block run if the property is read three times?

  • Three times
  • Once
  • Zero times
  • Twice

Answer: Once. lazy runs the block once and caches; later reads return the cached value.

When is a normal val computed?

  • Lazily, on first read
  • Never
  • Eagerly, right where it is declared
  • Only inside main()

Answer: Eagerly, right where it is declared. A regular val is computed eagerly, at the point of declaration.

Which delegate is appropriate for a deferred val of type Int?

  • lateinit var
  • by lazy
  • a nullable Int
  • an abstract property

Answer: by lazy. lateinit can't be used on Int or val, so use by lazy for a deferred Int val.

Why might you choose lateinit over a nullable type?

  • It allows null safely
  • It recomputes automatically
  • It avoids handling null on every access for a value you know will be set
  • It is faster to compute

Answer: It avoids handling null on every access for a value you know will be set. lateinit gives a non-null var so code skips ?. / !! checks for a value set later.

By default, is a lazy property thread-safe?

  • Yes, it is synchronized by default
  • No, never
  • Only on Android
  • Only for val of Int

Answer: Yes, it is synchronized by default. By default lazy uses synchronized mode, making first access thread-safe.