Kotlin interview questions

14 programming language interview questions on Kotlin, each with the correct answer and a full explanation.

What does this print?
data class P(val x: Int)
println("${P(1) == P(1)} ${P(1) === P(1)}")
Show answer

Answer

true false
== calls equals, which data classes generate from constructor properties. === checks reference identity, and these are two objects.

Source: Kotlin docs: Equality, Kotlin docs: Data classes

What does this print?
data class Q(val x: Int) {
    var y: Int = 0
}
val a = Q(1).apply { y = 5 }
println(a == Q(1))
Show answer

Answer

true
Generated equals, hashCode, toString and copy use only primary constructor properties. y lives in the body and is ignored.

Source: Kotlin docs: Data classes

What does this print?
val a = mutableListOf(1)
val b: List<Int> = a
a.add(2)
println(b)
Show answer

Answer

[1, 2]
List is a read only view, not an immutable copy. b and a refer to the same list. Use toList() for a snapshot.

Source: Kotlin docs: Collections overview

What does this print?
data class T(val tags: MutableList<String>)
val a = T(mutableListOf("x"))
val b = a.copy()
b.tags.add("y")
println(a.tags)
Show answer

Answer

[x, y]
copy() is shallow: both objects share the same list. Prefer immutable List fields, or copy the list explicitly.

Source: Kotlin docs: Data classes

Why does this not compile?
class A(var name: String?)

fun f(a: A) {
    if (a.name != null) println(a.name.length)
}
Show answer

Answer

Smart cast is impossible because name is a mutable property
The compiler cannot prove a var property is unchanged between the check and the use, since another thread could set it. Copy to a local val, or use a.name?.let { ... }.

Source: Kotlin docs: Type checks and casts

What does this print?
val r = listOf(1, 2, 3).asSequence()
    .map { print(it); it * 2 }
    .first()
println(r)
Show answer

Answer

12
Sequences are lazy and process one element at a time, so map runs only for 1, then first stops. A plain list maps all three first and would print 1232.

Source: Kotlin docs: Sequences

In Kotlin, a lateinit var is read before it is assigned. What happens?
Show answer

Answer

UninitializedPropertyAccessException
lateinit skips the initializer check at compile time and throws a specific exception on early access. Check ::prop.isInitialized if needed.

Source: Kotlin docs: Properties

In Kotlin, what is the default thread safety mode of by lazy?
Show answer

Answer

SYNCHRONIZED: the initializer runs once, under a lock
The default lazy is synchronized, so only one thread runs the initializer. PUBLICATION allows concurrent runs and keeps the first result. NONE is for single threaded use.

Source: Kotlin docs: Delegated properties

What does this print?
val s: String? = null
println(s?.length ?: -1)
Show answer

Answer

-1
s?.length is null when s is null, and ?: supplies the fallback.

Source: Kotlin docs: Null safety

In Kotlin, a coroutine needs to call a blocking JDBC driver. Which dispatcher fits?
Show answer

Answer

Dispatchers.IO
IO has a larger, elastic thread pool for blocking calls. Default is sized to CPU cores for computation, and blocking it starves other work. Main is the UI thread.

Source: Kotlin docs: Coroutine context and dispatchers

In Kotlin, inside a coroutine on a single threaded dispatcher, what is the difference between delay(1000) and Thread.sleep(1000)?
Show answer

Answer

delay suspends and frees the thread, sleep blocks it
delay suspends the coroutine so other coroutines can run on the thread, and it responds to cancellation. Thread.sleep holds the thread.

Source: Kotlin docs: Cancellation and timeouts

In Kotlin, inside coroutineScope, one of two launched children throws. What happens to the other?
Show answer

Answer

It is cancelled and the exception propagates out of coroutineScope
Structured concurrency cancels siblings and the parent when a child fails. Use supervisorScope when children should fail independently.

Source: Kotlin docs: Coroutine exceptions handling

What is the risk of this inside a coroutine?
try {
    work()
} catch (e: Exception) {
    log(e)
}
Show answer

Answer

It also catches CancellationException, so the coroutine keeps running after cancel
Cancellation is delivered as CancellationException, a subclass of Exception. Swallowing it breaks cooperative cancellation. Rethrow it, or catch narrower types.

Source: Kotlin docs: Cancellation and timeouts

In Kotlin, a MutableStateFlow holds 5, and you set value = 5 again. What do collectors see?
Show answer

Answer

Nothing, equal values are not emitted
StateFlow is conflated and uses equality, so setting an equal value is a no op. Use SharedFlow for events that must repeat.

Source: kotlinx.coroutines API: StateFlow

These questions come from the Language Gotchas pack in Bertopia.

More programming language topics

Practise these on your commute