Kotlin Data Class

Kotlin Data Class is a class marked with the data keyword to represent a value-holding model. It is commonly used for objects such as User, Book, Product, ApiResponse, or any model whose main purpose is to store and pass structured data.

A data class reduces boilerplate code because Kotlin automatically generates useful functions such as toString(), equals(), hashCode(), copy(), and component functions for destructuring declarations.

Also, Data classes are useful when a function has to return more than one value. All the values that are required to be returned are encapsulated in a data class and the object of data class is returned.

The structure of data class is similar to that of a usual Kotlin Class, except that the keyword data precedes the keyword class.

Kotlin Data Class Syntax

The basic syntax of a Kotlin data class is shown below. The primary constructor must contain at least one property, and every primary constructor parameter must be declared with val or var.

</>
Copy
data class ClassName(val property1: Type, val property2: Type)

For example, the following data class stores the name and price of a book.

</>
Copy
data class Book(val name: String, val price: Int)

Kotlin Data Class Rules

When creating a Kotlin data class, keep these rules in mind:

  • The class must have at least one parameter in the primary constructor.
  • All primary constructor parameters must be marked as val or var.
  • A data class cannot be declared as abstract, open, sealed, or inner.
  • Only properties in the primary constructor are used by generated functions such as equals(), hashCode(), toString(), copy(), and component functions.
  • If a data class needs a no-argument constructor on the JVM, provide default values for all primary constructor parameters.

Example 1 – Kotlin Data Class

In the below example we shall define a data class “Book” with variables “name” and “price“. And add objects of Book to an array of Book, and finally print them.

example.kt

</>
Copy
import java.util.ArrayList

fun main(args: Array) {
    var books: ArrayList = ArrayList()
    books.add(Book("The Last Sun",250))
    books.add(Book("Three Friends",221))
    for(book in books)
        println(book)
}

data class Book(val name: String = "", val price: Int = 0)

The default values (name=””, price=0) are provided in the definition of data class.

Output

Book(name=The Last Sun, price=250)
Book(name=Three Friends, price=221)

The output is readable because the data class automatically provides a toString() implementation. In a regular class, printing an object usually shows a less useful reference-style string unless toString() is overridden manually.

Generated Functions in a Kotlin Data Class

For the primary constructor properties, Kotlin generates the following common functions for a data class:

  • toString() prints the class name and property values.
  • equals() compares two data class objects by their property values.
  • hashCode() returns a hash value based on the primary constructor properties.
  • copy() creates another object with the same values or with selected values changed.
  • componentN() functions support destructuring declarations such as val (name, price) = book.

Value Comparison with equals() in Kotlin Data Class

Data classes compare objects by values in the primary constructor. This makes them suitable for model objects where two instances should be considered equal when their stored values are equal.

example.kt

</>
Copy
fun main() {
    val book1 = Book("The Last Sun", 250)
    val book2 = Book("The Last Sun", 250)
    val book3 = Book("Three Friends", 221)

    println(book1 == book2)
    println(book1 == book3)
}

data class Book(val name: String, val price: Int)

Output

true
false

The == operator calls equals() in Kotlin. Here, book1 and book2 are different objects, but they are equal because their name and price values are the same.

Modify & Copy a Data Class

Kotlin allows copying an existing data class object to a new variable as is or with modifications to some of the parameters of Data Class.

The following example demonstrates how to copy a data class object to other; modify and copy a data class object to other.

example.kt

</>
Copy
import java.util.ArrayList

fun main(args: Array) {
    var books: ArrayList = ArrayList()
    var book1 = Book("The Last Sun",250)
    var book2 = Book("Three Friends",222)
    var book3 = book1.copy()
    var book4 = book2.copy(name="The Last Bond")
    var book5 = book2.copy(price=263)
    books.add(book1)
    books.add(book2)
    books.add(book3)
    books.add(book4)
    books.add(book5)
    
    for(book in books)
    	println(book)
}

data class Book(val name: String = "", val price: Int = 0)
  • book1, book2 are new objects created.
  • book3 is a copy of book1.
  • book4 is a copy of book2 with name modified to “The Last Bond”.
  • book5 is a copy of book2 with price modified to 263.

Output

Book(name=The Last Sun, price=250)
Book(name=Three Friends, price=222)
Book(name=The Last Sun, price=250)
Book(name=The Last Bond, price=222)
Book(name=Three Friends, price=263)

The copy() function is especially useful when the data class uses val properties. Instead of changing the existing object, you create a new object with the required changes.

Component Functions

Component functions are used to access individual properties of a data class. An example is provided below, where we access the properties, “name” and “price” of data class “Book” using component functions.

example.kt

</>
Copy
fun main(args: Array) {
    var book1 = Book("The Last Sun",250)
    var name = book1.component1();
    var price = book1.component2();
    println("$name has a price of $$price")
}

data class Book(val name: String = "", val price: Int = 0)

Output

The Last Sun has a price of $250

Destructuring a Kotlin Data Class Object

Instead of calling component1() and component2() directly, you can use destructuring declarations. Destructuring is a cleaner way to assign data class property values to separate variables.

example.kt

</>
Copy
fun main() {
    val book = Book("The Last Sun", 250)
    val (name, price) = book

    println(name)
    println(price)
}

data class Book(val name: String, val price: Int)

Output

The Last Sun
250

Properties Inside Kotlin Data Class Body

Only properties declared in the primary constructor are used in the automatically generated data class functions. Properties declared inside the class body are not included in equals(), hashCode(), toString(), copy(), or destructuring component functions.

example.kt

</>
Copy
fun main() {
    val user1 = User("Alex")
    val user2 = User("Alex")

    user1.age = 25
    user2.age = 30

    println(user1)
    println(user1 == user2)
}

data class User(val name: String) {
    var age: Int = 0
}

Output

User(name=Alex)
true

Even though age is different for the two objects, the equality result is true because age is declared in the class body, not in the primary constructor.

Kotlin Class vs Data Class

A regular Kotlin class is suitable when the object mainly represents behavior, state changes, inheritance design, or custom lifecycle logic. A Kotlin data class is suitable when the object mainly represents values.

FeatureRegular Kotlin classKotlin data class
Main purposeBehavior and custom object designStoring and passing data
toString()Must be overridden manually for readable outputGenerated automatically
equals() and hashCode()Must be overridden manually for value comparisonGenerated automatically using primary constructor properties
copy()Not available by defaultGenerated automatically
DestructuringNot available unless component functions are definedAvailable through generated component functions

When to Use Kotlin Data Class

Use a Kotlin data class when the class is mainly a container for values. Common examples include:

  • API response models in Android or backend applications.
  • Database row models or DTOs.
  • Objects returned from a function when more than one value is needed.
  • Configuration or form-state objects.
  • Immutable value objects created with val properties and updated using copy().

Avoid using a data class only because it is shorter to write. If the class has important behavior, inheritance needs, or identity-based comparison, a regular class may be a better choice.

Common Kotlin Data Class Mistakes

  • Declaring constructor parameters without val or var: data class primary constructor parameters must be properties.
  • Expecting body properties to take part in equality: only primary constructor properties are used by generated functions.
  • Using var everywhere: data classes are often easier to reason about when properties are immutable with val.
  • Expecting copy() to deeply copy nested objects: copy() creates a new outer object, but referenced nested objects are still shared unless you copy them separately.
  • Trying to make a data class open: data classes cannot be declared with the open modifier.

Kotlin Data Class FAQ

What is a Kotlin data class used for?

A Kotlin data class is used to store and pass data in a structured form. It is commonly used for model classes, DTOs, API responses, database records, and function return objects that contain multiple values.

What functions are generated for a Kotlin data class?

Kotlin generates toString(), equals(), hashCode(), copy(), and component functions for properties declared in the primary constructor of a data class.

Can a Kotlin data class have methods?

Yes. A Kotlin data class can have functions and properties inside its body. However, properties declared inside the body are not included in the generated equals(), hashCode(), toString(), copy(), or component functions.

What is the difference between a class and a data class in Kotlin?

A regular class does not automatically provide value-based equals(), readable toString(), copy(), or destructuring support. A data class provides these automatically for the primary constructor properties.

Does copy() in Kotlin data class create a deep copy?

No. The generated copy() function creates a shallow copy. If the data class contains references to mutable objects, both the original and copied object may still refer to the same nested object.

Kotlin Data Class Editorial QA Checklist

  • Confirm that every data class example has at least one primary constructor property.
  • Check that constructor parameters in data class examples use val or var.
  • Verify that examples distinguish primary constructor properties from class-body properties.
  • Ensure copy() examples do not imply deep copying of nested mutable objects.
  • Use language-kotlin for Kotlin examples and output for result blocks.

Conclusion

In this Kotlin TutorialKotlin Data Class, we have learnt what a Kotlin Data Class is, how to initialize an object of data class, how to copy one data class object to other with some properties(or you can say parameters) modified, and also to access the individual parameters of Kotlin data class using component functions.

We also covered generated functions, value comparison, destructuring declarations, class-body properties, and common mistakes to avoid while using Kotlin data classes.