Explanation of Data Classes in Kotlin

Posted on 2025-12-27 by Burak Hamdi TUFAN
General Programming
Explanation of Data Classes in Kotlin
Hello everyone, in this article we are going to discover Data Classes in Kotlin with the help of code examples.

Let's get started.

What Are Data Classes?

A data class in Kotlin is designed to store the data.
When you declare a class as a data class using the data keyword, Kotlin automatically generates the following methods for you:
  • equals() and hashCode()
  • toString()
  • copy()
  • componentN() functions (for destructuring declarations)

This automatic generation allows you to focus on logic rather than repetitive boilerplate.

Data classes in Kotlin are a perfect example of how Kotlin simplifies coding and holding data. Data classes are also provides:
  • Cleaner code
  • Built-in equality and hashing
  • Easy object copying
  • Destructuring support
  • Immutability by default
Let's define a simple data class in Kotlin:

data class User(
    val id: Int,
    val name: String,
    val email: String
)
When we define a data class, Kotlin also generates below methods for us:
  • equals() and hashCode() for proper comparison
  • toString() that prints user-friendly output
  • copy() to clone objects with modifications
  • Destructuring Declarations: unpacking properties directly into variables

Why we should use Data Classes?

Instead of writing tedious getters, setters, and equals() manually, data classes give you a minimal, readable representation.

Below you can see an example of above defined data class:

val user1 = User(1, "Alice", "alice@example.com")
val user2 = User(1, "Alice", "alice@example.com")

// ...
println(user1 == user2)  // true, thanks to auto-generated equals()
println(user1)           // User(id=1, name=Alice, email=alice@example.com)

Please pay attention to the equality check is content-based, not reference-based unlike java.

We can use copy() for Object Cloning

The copy() function makes it easy to clone data objects while changing selected properties.

Below you can see an example about it

val updatedUser = user1.copy(email = "alice.new@example.com")
println(updatedUser) // User(id=1, name=Alice, email=alice.new@example.com)

This is especially useful in immutable architectures.

Destructuring Declarations

Data classes support object destructuring. So we can unpack the data classes directly into variables to use the individual fields of class.

val (id, name, email) = user1
println("ID: $id, Name: $name, Email: $email")

Equality and Hashing

Since Kotlin handles equals() and hashCode() generation automatically, two data objects with the same content are considered equal. This is a perfect feature for working with collections or for entity comparisons.

Below you can see a code example:

val users = hashSetOf(user1)
println(users.contains(user2))  // true

Limitations on Data Classes

There are a few key limitations to keep in mind:
  • A data class must have at least one primary constructor parameter.
  • These parameters must be marked as val or var.
  • Data classes cannot be abstract, sealed, or inner classes.
  • You can customize generated methods by overriding them if needed.
Here you can see an example of a customized data class:

data class Point(val x: Int, val y: Int) {
    // Custom method
    fun distanceFromOrigin(): Double = Math.sqrt((x * x + y * y).toDouble())

    // Override toString()
    override fun toString() = "Point($x, $y)"
}
Data classes are very useful with
  • DTOs (Data Transfer Objects)
  • API responses
  • Immutable state models (especially in Android apps using MVVM)
  • Local persistence entities

Summary

By using data classes, you reduce boilerplate and improve clarity which is a great win for every Kotlin developer.

That is All

Burak Hamdi Tufan


Tags
Share this Post
Send with Whatsapp