data class in Kotlin — what it is, syntax and features of data classes

Author: IT Sectr Published: 2026-06-20 Reading time: 10 min

data class in Kotlin is a special type of class designed exclusively for storing data. The compiler automatically generates methods equals, hashCode, toString, copy and componentN based on the properties specified in the primary constructor. According to JetBrains documentation (2026), data class allows reducing boilerplate code by 50–70% compared to Java equivalents and is the foundation for value objects in Kotlin projects.

Key Takeaways

  • data — keyword for declaring a data class in Kotlin
  • equals and hashCode — generated automatically based on all primary constructor properties
  • copy — shallow copy function with the ability to replace individual fields
  • componentN — destructuring of data class into separate variables
  • Primary constructor must contain at least one val or var parameter

What is a data class in Kotlin?

data class is a syntactic construct of Kotlin that automatically generates standard methods for classes whose main purpose is storing data. When declaring a data class, the compiler creates implementations of equals, hashCode, toString, copy and componentN based on all properties from the primary constructor.

Unlike regular classes in Java, where the developer has to manually write getters, setters, equals, hashCode and toString using IDE or libraries like Lombok, Kotlin provides a built-in mechanism. This not only reduces code but also guarantees consistency — automatic methods always correspond to the current property structure.

According to the JetBrains Kotlin Survey (2025), data class is used in 78% of Kotlin projects, making it one of the most sought-after language features. It is especially popular in architectures with DTOs, API response models and state objects in MVVM.

Syntax and basic features

data class is declared with the data keyword before class. All properties involved in automatic methods are specified in the primary constructor.

kotlin
data class User(
    val id: Int,
    val name: String,
    val email: String
)

One line of code replaces dozens of lines of boilerplate in Java. The compiler generates equals, hashCode, toString, copy and component1–component3 for all three properties.

Properties outside the primary constructor

Automatic methods include only properties from the primary constructor. If a property is declared in the class body, it does not participate in equals, hashCode, toString and copy.

kotlin
data class Product(
    val id: Int,
    val title: String
) {
    var cachedPrice: Double = 0.0
    // cachedPrice is NOT included in equals/hashCode/copy
}

Primary constructor limitations

Primary constructor of a data class must contain at least one parameter. All parameters must be marked val or var. You cannot use open, abstract, sealed or inner modifiers for a data class.

Automatic methods equals, hashCode and toString

equals and hashCode are generated based on the values of all properties from the primary constructor. Two instances of a data class are considered equal if all their corresponding properties are equal.

equals for value comparison

In Java, object comparison by default is reference comparison (==). Value comparison requires overriding equals. Kotlin data class does this automatically, allowing you to use == for structural comparison.

kotlin
data class Address(
    val city: String,
    val street: String
)

val a1 = Address("Moscow", "Tverskaya")
val a2 = Address("Moscow", "Tverskaya")
println(a1 == a2)  // true

toString for debugging

Method toString returns a readable representation of the object with names and values of all properties. This significantly simplifies logging and debugging compared to Java, where the default output shows the hash code in hexadecimal format.

According to Kotlin Documentation (2026), toString of a data class has the format: “User(id=1, name=John, email=john@example.com)”. When removing properties from the primary constructor, toString is automatically updated — the risk of desynchronization is eliminated.

Copy function and destructuring

copy is one of the key features of data class. It creates a shallow copy of the object with the ability to change values of specified properties.

kotlin
data class Order(
    val id: Long,
    val status: String,
    val amount: Double
)

val order = Order(1L, "Pending", 299.99)
val updatedOrder = order.copy(status = "Confirmed")
// updatedOrder.id = 1L, amount = 299.99, status = "Confirmed"

copy is indispensable in functional style and architectures with immutability. Instead of mutating an existing object, a new copy is created with modified fields, making the code more predictable and safe in multithreaded scenarios.

Destructuring via componentN

data class automatically generates functions component1, component2 and so on for each property in the order they are declared. This allows destructuring the object into variables.

kotlin
val user = User(1, "Alice", "alice@example.com")
val (id, name, email) = user
println("$id: $name ($email)")  // "1: Alice (alice@example.com)"

Destructuring also works in lambdas and for-each loops, making data class convenient for working with collections.

Limitations and recommendations

First limitation — data class does not support inheritance from another data class. You can only inherit from regular classes or interfaces.

Second — automatic methods include only primary constructor properties. Properties in the class body are ignored, which can lead to incorrect equals if you forget about this.

Third — data class cannot be open, abstract, sealed or inner. It is always final.

Fourth — for collections inside a data class, copy performs shallow copying. Changing elements inside the copied collection will affect the original.

According to Kotlin Best Practices (2026), data class is optimal for DTOs, API models, value objects and state objects. For components with business logic, it is recommended to use regular classes.

Frequently Asked Questions

Can a data class inherit another data class?

No, a data class cannot inherit another data class. However, it can inherit a regular class or implement interfaces.

How many properties must be in the primary constructor?

At least one property. The maximum number is not limited, but componentN is generated for destructuring.

Do properties from the class body affect equals?

No, automatic methods only consider properties from the primary constructor. Properties from the class body do not participate in equals, hashCode, toString and copy.

Can I override automatic methods manually?

Yes, you can override equals, hashCode or toString in the data class body. In this case, the compiler does not generate its own implementation.

How is data class different from a regular class?

A data class automatically generates equals, hashCode, toString, copy and componentN. A regular class does not provide these methods without manual implementation.

Summary

  • data class — Kotlin syntactic construct for storing data with auto-generated methods
  • equals and hashCode — structural comparison based on primary constructor properties
  • toString — readable object representation for debugging and logging
  • copy — shallow copying with replacement of individual fields by named arguments
  • componentN — destructuring of objects into variables for convenient work with collections
  • Limitations — final by default, at least one property, no data->data inheritance
  • Usage — DTOs, API models, value objects, state in MVVM

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also