How to create empty constructor for data class in Kotlin Android
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Kotlin data classes require all primary constructor parameters to be initialized, so they do not have a no-argument constructor by default. This causes issues with libraries like Firebase, Room, Gson, and Jackson that need to create instances via reflection using an empty constructor. The solution is to provide default values for all parameters, use the no-arg compiler plugin, or switch to a regular class for complex cases.
The Problem
Firebase Realtime Database, Firestore, and many JSON parsers create objects by calling the no-arg constructor and then setting fields via reflection. Without a no-arg constructor, deserialization fails.
Solution 1: Default Values for All Parameters (Recommended)
When every parameter has a default value, Kotlin generates a no-arg constructor automatically. Firebase, Gson, and other reflection-based libraries can instantiate the class without arguments.
Choosing Appropriate Defaults
| Type | Typical Default |
| String | "" |
| Int, Long, Double | 0, 0L, 0.0 |
| Boolean | false |
| List | emptyList() |
| Map | emptyMap() |
| Nullable | null |
Solution 2: Nullable Types with null Default
This approach makes it clear that fields may not be set. It works well when you need to distinguish "not provided" from "empty string," but forces null checks everywhere you use the fields.
Solution 3: Secondary Constructor
This works but has a drawback: the secondary constructor is not used by copy() or destructuring. Default values in the primary constructor are usually cleaner.
Solution 4: no-arg Compiler Plugin
The Kotlin no-arg plugin generates a synthetic no-arg constructor for annotated classes without changing your source code:
The generated constructor is only visible to reflection — you cannot call User() from Kotlin code directly. This is the cleanest approach when you want immutable val properties without fake defaults.
Firebase-Specific Pattern
Firebase requires:
- A no-arg constructor (provided by default values)
- Properties must be
varor have matching setter methods — but Firestore actually works withvalby using the constructor parameters directly if they match field names
Room Database Pattern
Room uses the primary constructor directly and matches column names to parameter names. Default values ensure Room can create instances during query result mapping.
Gson and Moshi
Common Pitfalls
- Using
varunnecessarily: Many developers switch tovarfor Firebase compatibility, butvalwith default values works in most cases. Prefervalfor immutability. - Forgetting one parameter's default: If even one parameter lacks a default, no no-arg constructor is generated. All parameters must have defaults for the zero-argument form to exist.
- Empty string vs null ambiguity: Defaulting to
""makes it impossible to distinguish "field was empty" from "field was never set." Use nullable types (String? = null) when this distinction matters. - ProGuard/R8 stripping constructors: Minification can remove the generated no-arg constructor. Add keep rules for data classes used with reflection:
-keep class com.example.models.** { *; }. - Assuming
copy()uses secondary constructors: Thecopy()function always uses the primary constructor. Default values in the primary constructor are preserved; secondary constructor defaults are not used bycopy().
Summary
- Give all primary constructor parameters default values to get a free no-arg constructor
- Use
"",0,false,emptyList(), ornullas defaults depending on the type - The
no-argcompiler plugin generates a reflection-only constructor without changing source code - Firebase, Room, Gson, and most reflection-based libraries work when default values are provided
- Prefer
valproperties with defaults overvar— immutability is a Kotlin strength

