thecodex.expert · The Codex Family of Knowledge
Kotlin

Data Classes

Java’s record eventually copied this idea years later — Kotlin’s data class has offered equals, hashCode, toString, and more from one keyword since its very first stable release.

Kotlin 2.1 Based on primary-constructor properties only Last verified:
Canonical Definition

data class User(val name: String, val age: Int) generates, purely from those primary-constructor properties: a value-based equals()/hashCode() pair, a readable toString() (User(name=Alice, age=30)), a copy() function for creating a new instance with select properties changed, and component1()/component2() functions enabling destructuring into separate variables. Crucially, only properties declared IN the primary constructor participate in this generated behavior; a property added in the class body is excluded from equals, hashCode, toString, and copy entirely.

One line replaces dozens

equals compares by VALUE (not reference), and toString produces something actually readable in logs or debugger output — both generated automatically, with zero manual implementation.

Kotlinbasic_data_class.kt
data class User(val name: String, val age: Int)

val u1 = User("Alice", 30)
val u2 = User("Alice", 30)

println(u1)              // User(name=Alice, age=30) — readable, auto-generated
println(u1 == u2)        // true — compares by VALUE, not reference

copy(): a modified duplicate, without mutation

copy() creates a NEW instance, changing only the named parameters and keeping everything else identical — idiomatic for updating an immutable data class without hand-writing a new constructor call listing every property.

Kotlincopy_function.kt
val original = User("Alice", 30)
val older = original.copy(age = 31)   // NEW instance — original is untouched

println(original)   // User(name=Alice, age=30)
println(older)         // User(name=Alice, age=31)

Destructuring: unpacking into separate variables

This works because data classes automatically generate component1(), component2(), etc. — the destructuring syntax is really calling those functions in order behind the scenes.

Kotlindestructuring.kt
val user = User("Alice", 30)
val (name, age) = user   // destructures into two separate variables

println("$name is $age")   // "Alice is 30"

Sources

1
JetBrains. Kotlin Documentation, "Data classes," kotlinlang.org/docs/data-classes.html.