Empty Constructor in Kotlin Data Class: 5 Mistakes and How to Fix Them

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Doesn't a Data Class Want to Be Empty?

\n\n

Have you ever tried to create a data class in Kotlin for Android and were surprised to find that the compiler refuses to accept an empty constructor? If so, you are not alone. This question has gathered thousands of views on Stack Overflow, meaning hundreds of developers (from beginners to experienced) have stumbled over the same rake.

\n\n

Why does this happen? The thing is, a data class in Kotlin is not just a class for storing data. It automatically generates equals(), hashCode(), toString(), copy(), and componentN() functions. And for all this magic, it needs a primary constructor with at least one parameter. Without it, it's impossible.

\n\n

In this article, we will break down the top 5 mistakes developers make when trying to create an empty constructor for a data class in Kotlin Android and show you how to avoid them. Let's go!

\n\n

Mistake #1: Directly Declaring an Empty Constructor

\n\n

The most common mistake is trying to write something like:

\n\n
// ❌ This is not allowed!\ndata class User {\n    constructor() : this() // Compilation error\n}\n
\n\n

Kotlin strictly requires that the primary constructor be declared in the class header. If you try to create a secondary constructor without parameters that calls itself, you will get infinite recursion and a compilation error.

\n\n

Solution: Default Values

\n\n

The simplest and most elegant way is to set default values for all parameters of the primary constructor:

\n\n
// ✅ Correct: default values\ndata class User(\n    val name: String = "",\n    val age: Int = 0,\n    val email: String = ""\n)\n\n// Now you can create an object without arguments\nval emptyUser = User()\nprintln(emptyUser) // User(name=, age=0, email=)\n
\n\n

This approach works "out of the box" and does not require any additional plugins or annotations. You get a full-fledged empty constructor, and all fields are initialized with default values.

\n\n

Mistake #2: Ignoring Library Requirements (Room, Retrofit, Gson)

\n\n

Many Android libraries require an empty constructor to create objects via reflection. A classic example is Room:

\n\n
// ❌ Room will throw an error\n@Entity\ndata class User(\n    @PrimaryKey val id: Int,\n    val name: String,\n    val age: Int\n)\n
\n\n

When trying to use such a data class with Room, you will get an exception: Cannot instantiate User using no-arg constructor. Similar problems arise with Gson and Retrofit when deserializing JSON.

\n\n

Solution: Default Values + Nullable Types

\n\n

For Room, it's enough to add default values:

\n\n
// ✅ Room is happy\n@Entity\ndata class User(\n    @PrimaryKey val id: Int = 0,\n    val name: String = "",\n    val age: Int = 0\n)\n
\n\n

For Gson and Retrofit, it's often easier to use nullable types:

\n\n
// ✅ For working with JSON\ndata class ApiResponse(\n    val status: String? = null,\n    val data: List<Item>? = null\n)\n
\n\n

But be careful: nullable types can lead to NPE if you forget to check the value. Use them consciously.

\n\n

Mistake #3: Forgotten Kotlin No-Arg Plugin

\n\n

Sometimes default values are not suitable. For example, if you are using Jackson for serialization and you need specific types without nullable. In this case, the kotlin-noarg plugin comes to the rescue.

\n\n

Many developers mistakenly think that simply adding a dependency to build.gradle is enough. But without proper configuration, the plugin will not work.

\n\n

Solution: Correct No-Arg Configuration

\n\n

Add the plugin to build.gradle.kt:

Blogs

Book Recommendations