Blog Infos
Author
Published
Topics
, , , ,
Published

Image generated by the author using Midjourney

In a previous article, we discussed why using var in the constructor of a Kotlin data class can lead to unexpected behavior and subtle bugs.
Now, let’s look at another important detail that often goes unnoticed:
why you should avoid using Array types in the constructor of a data class.

Kotlin’s data class feature simplifies the creation of immutable models by automatically generating equals()hashCode()copy(), and toString() based on the primary constructor properties.
For most use cases, this behavior works exactly as expected.

However, when you use an Array as a property, the behavior of equals()hashCode(), and toString() may not match your intentions.
Instead of comparing the contents of the array, Kotlin (and Java) compare the object references.

This can lead to subtle and hard-to-detect bugs — especially when your data classes are used in sets, maps, or caching systems.

In this article, we’ll see why using Array inside a data class constructor is risky, and what you should do instead.

Featured On
Working correctly with List

Let’s start with a simple example where the friends property is a List inside a data class:

data class Person(
    val name: String,
    val friends: List<String>
)

fun main() {
    val person1 = Person(
        name = "Mike",
        friends = listOf("Mary", "John", "Tom")
    )

    val person2 = Person(
        name = "Mike",
        friends = listOf("Mary", "John", "Tom")
    )

    println(person1 == person2)
}

Output:

true

In this case, the two Person instances are considered equal.

This is because List in Kotlin overrides equals() and hashCode() to compare the contents of the list, not just the object references.

Two lists are considered equal if:

  • They contain the same elements,
  • In the same order.

As a result, Kotlin’s generated equals() and hashCode() for the data class properly compare the friends list by value.

Problem when using Array

Now, let’s modify the example slightly by changing the friends property to use an Array instead of a List:

data class Person(
    val name: String,
    val friends: Array<String>
)

fun main() {
    val person1 = Person(
        name = "Mike",
        friends = arrayOf("Mary", "John", "Tom")
    )

    val person2 = Person(
        name = "Mike",
        friends = arrayOf("Mary", "John", "Tom")
    )

    println(person1 == person2)
}

Output:

false

Even though both Person instances have the same name and the same friends, the comparison returns false.

This happens because Array in Kotlin (and Java) does not override equals() and hashCode() to compare the contents of the array.

In contrast, collections like ListSet, and Map correctly override these methods to compare contents structurally in both Kotlin and Java.

Instead, Array uses reference equality — two arrays are considered equal only if they are the same instance in memory.

As a result, even identical-looking objects are treated as different when arrays are involved.

IDE warning

Modern IDEs like Android Studio and IntelliJ IDEA can detect this potential problem.
If you declare an Array as a property inside a data class, the IDE will highlight it with a warning:

Example warning from Android Studio

Property with ‘Array’ type in a ‘data’ class: it is recommended to override equals() and hashCode()

This warning is a strong signal that using arrays inside data classes can easily lead to incorrect or unpredictable behavior — even if the code compiles without errors.

Why this causes real issues

In some cases, data class instances are used as keys in HashMap or as elements in HashSet.
Both collections rely on consistent implementations of hashCode() and equals() to work correctly.

When a data class contains an Array, these operations are based on the reference of the array, not its contents.

This leads to problems such as:

  • Cache misses when using objects as keys in maps,
  • Duplicate entries in sets,
  • Incorrect behavior in collections that expect structural equality.

Even if two objects have identical data, the program treats them as different — simply because their arrays are different instances in memory.

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Kobweb:Creating websites in Kotlin leveraging Compose HTML

Kobweb is a Kotlin web framework that aims to make web development enjoyable by building on top of Compose HTML and drawing inspiration from Jetpack Compose.
Watch Video

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kobweb

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author o ...

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kob ...

Jobs

How to avoid this problem

The solution is simple: avoid using Array types inside the primary constructor of a data class.

Instead, use collection types that correctly override equals() and hashCode(), such as ListSet, or Map.

These types compare their contents structurally, not by reference, and fully support the behavior expected from data classes.

Choosing the right types ensures that equality checks, hashing, and collection behavior work as intended — even in large and complex applications.

Conclusion

Kotlin’s data class feature automatically generates equals()hashCode(), and other utility methods based on the properties declared in the primary constructor.
This works reliably — as long as the types used behave correctly.

Array types in Kotlin (and Java) do not override equals() and hashCode() to compare contents.
Instead, they use reference equality, which can lead to subtle and hard-to-detect bugs when comparing objects or working with collections.

Modern IDEs like Android Studio can warn you about this issue.
But they cannot explain why it happens, what consequences it brings, or how to design safer models.

Understanding these details helps not only to fix isolated problems,
but also to build predictable, safe, and maintainable data models as your applications grow.

When working with collections inside a data class, prefer ListSet, or Map instead of Array.

Choosing the right types is a small decision that helps prevent much larger problems later.

If you found this article helpful

If you enjoyed this article or learned something new, consider leaving a clap — it helps others discover it.
You can also follow me on Medium for more articles about Kotlin, Android development, and practical engineering topics.

You might also like:

Anatolii Frolov
Senior Android Developer
Writing honest, real-world Kotlin & Jetpack Compose insights.
📬 Follow me on Medium

This article was previously published on proandroiddev.com.

Menu