Interview prep · Stage 1: Kotlin and DSA basics
Kotlin data class interview questions
One opener and four harder follow-ups. Each step builds on the last, the way a real interviewer digs.
Try each question out loud before you open the answer.
Opening question
What does the data keyword add to a class?
Show answer
Junior answer
It generates equals(), hashCode(), toString(), copy() and component1()..componentN(), so two objects with the same values are equal.
Senior answer
Same five, but only from primary constructor properties. The class stays final, and it must have at least one val/var constructor parameter. You can override equals/hashCode/toString, but not copy or componentN.
What they're really checking: That you know it is code generation, not a new kind of class.
Follow-up 1
Are these two orders equal?
Show answer
data class CartItem(val name: String, val price: Int)
data class Order(val id: String, val items: List<CartItem>) {
var isSeen: Boolean = false
}
val items = listOf(CartItem("Lassi", 60))
val a = Order("A1", items).apply { isSeen = true }
val b = Order("A1", items)
println(a == b) // ?Answer
true. isSeen is in the body, so equals() ignores it. toString() hides it, and a.copy().isSeen is false.
What they're really checking: The trap is saying false because "the objects are different".
Follow-up 2
The cart screen doesn't update. Why?
Show answer
data class CartState(val items: MutableList<CartItem>)
val state = MutableStateFlow(CartState(mutableListOf())) // in the ViewModel
val item = CartItem("Lassi", 60)
val old = state.value
old.items.add(item)
state.value = old.copy()Junior answer
The list was changed in place, so the new state looks equal to the old one and StateFlow skips it.
Senior answer
add() changes the list inside the current state. copy() is shallow, so the new state points to that same list and equals() returns true. StateFlow drops a value equal to the current one, so collectors never see it. Fix: read-only List and state.update { it.copy(items = it.items + item) }, which builds a new list.
What they're really checking: In-place mutation + shallow copy + equality-based conflation, a real production bug.
Follow-up 3
A data class has a private constructor. What's the problem?
Show answer
data class Coupon private constructor(val percent: Int) {
companion object {
fun of(percent: Int): Coupon? =
if (percent in 1..50) Coupon(percent) else null
}
}
val coupon = Coupon.of(20)!!
val tooBig = coupon.copy(percent = 90)Answer
The generated copy() is public, so it skips the 1..50 check in of(). Since Kotlin 2.0.20 the compiler warns about this; as of Kotlin 2.4.21 (November 2026) it is still a warning (KT-11914). @ConsistentCopyVisibility makes copy() private now; @ExposedCopyVisibility keeps it public and silences the warning on the class.
Follow-up 4
Why prefer val in a data class you put in a set or use as a map key?
Show answer
data class Tag(var label: String)
val tag = Tag("veg")
val tags = hashSetOf(tag)
tag.label = "spicy"
println(tags.contains(tag)) // false, but tags.size is still 1Answer
hashCode() uses the properties. When a var changes after the object is in a HashSet or HashMap, its hash changes, so the lookup goes to the wrong bucket and can't find an object that is still inside.
Say it in 30 seconds
Show the answer
A data class is a final class where the compiler writes equals, hashCode, toString, copy and componentN from the primary constructor properties. Body properties don't count, and copy is shallow, which matters with mutable lists and StateFlow. If the constructor is private, add @ConsistentCopyVisibility.