val/var, null safety & the type system
Kotlin's type system separates nullable and non-nullable types: a String can never be null, a String? can. This catches most of Java's NullPointerExceptions at compile time.
Variable declarations:
val— a read-only reference: assigned once, never reassigned. It does not mean the object is immutable —val list = mutableListOf(1)still lets you mutate the list.var— a mutable reference.
A frequent interview probe: "does val mean immutable?" The correct answer: val makes the reference immutable, not the object.
| Operator | What it does | When to use |
|---|---|---|
| `?.` (safe call) | Returns null if the receiver is null | The default — anywhere null is possible |
| `?:` (Elvis) | Provides a fallback when null | For defaults or early returns |
| `!!` (not-null assertion) | Throws NPE if null | Almost never — considered a code smell |
| `lateinit var` | A non-null var assigned later | Fields initialized late via DI/lifecycle |
| `by lazy { }` | A val computed on first access | Expensive values needed once |
Interview trap: lateinit works only with var and reference types, while lazy only with val. Accessing an uninitialized lateinit throws UninitializedPropertyAccessException — checkable via ::field.isInitialized. In banking codebases !! is usually blocked in code review.
🛠 Practice task
In Kotlin Playground write a small Account model: val fields, one nullable (primaryCard: Card?).
- Write one line using
!!and crash it on purpose with a null — read the stack trace. - Rewrite that line with
?.+?:. - Declare a
lateinit var, read it before assignment to see the exception, then guard it with::field.isInitialized.
Done when: you can explain each of the three outcomes in one sentence.
📚 Sources and documentation
- Null safety — Kotlin docsofficialkotlinlang.org
- Properties (val/var, lateinit, lazy)officialkotlinlang.org
- Kotlin Playgroundofficialplay.kotlinlang.org
Run the snippets in the browser.