1. Overview

In this tutorial, we’ll show how to create a class instance with optional fields. First, we’ll show how to do it with a primary constructor with default values set to null. Additionally, we’ll show how to use a secondary constructor with default values.

2. Initialize Values With Null

In Kotlin, a data class represents a data container object. By default, it exposes a primary constructor, which requires all fields to be provided. Let’s create an example:

class DataClassWithMandatoryFields(
    val name: String,
    val surname: String,
    val age: Number
)

Now, the instance creation looks like:

val objectWithAllValuesProvided = DataClassWithMandatoryFields("John", "Deere", 82)

By default, in the data class, all fields are mandatory in the primary constructor. In case we don’t provide a value for any fields, the compiler throws an exception: “No value passed for parameter ‘<parameter name>'”.

Let’s write a new data class where the fields aren’t mandatory. We’ll modify the constructor and initialize all values with null:

class DataClassWithNullInitializedFields(
    val name: String? = null,
    val surname: String? = null,
    val age: Number? = null
)

Now, we can create an instance with no value provided. Additionally, we can provide selected values:

val objectWithNullInitializedFields = DataClassWithNullInitializedFields()
val objectWithNameInitializedFields = DataClassWithNullInitializedFields(name = "John")

However, such an approach means that we must check nullability before we access the field’s properties:

assertThat(objectWithNameInitializedFields.name?.length).isEqualTo("4")

3. Set Default Values in Primary Constructor

After that, let’s improve the previous version and eliminate nullability. For all constructor parameters, we set a default value:

class DataClassWithDefaultValues(
    val name: String = "",
    val surname: String = "",
    val age: Number = Int.MIN_VALUE
)

Thanks to that, we avoid the need for “safe calls” to handle null values. Similarly, we can create an object with some fields provided as in the previous example:

val dataClassWithDefaultValues = DataClassWithDefaultValues()
val dataClassWithNameProvided = DataClassWithDefaultValues(name = "John")

And now, we don’t have to check the nullability of the object’s fields:

assertThat(dataClassWithNameProvided.name.length).isEqualTo(4)

4. Secondary Constructor With Default Values

Now, let’s modify the approach with default values. Instead of default values in the primary constructor, we create secondary constructors:

class DataClassWithSecondaryConstructors(
    val name: String,
    val surname: String,
    val age: Number
) {
    constructor() : this("", "Doe", Int.MIN_VALUE)
    constructor(name: String) : this(name, "Deere", Int.MIN_VALUE)
    constructor(name: String, surname: String) : this(name, surname, Int.MIN_VALUE)
}

The construction of an object looks the same as in the previous example:

val dataClassWithSecondaryConstructors = DataClassWithSecondaryConstructors()
val objectWithNameSet = DataClassWithSecondaryConstructors(name = "John" )

As a result, we can set different defaults depending on the constructor. In our example, when no value is provided, we set the surname value to “Doe”. In case only the name is provided, we set the surname to “Deere”:

assertThat(objectWithNameSet.surname).isEqualTo("Deere")

5. Conclusion

In this short article, we showed how to create a class instance with optional fields. First, we showed how to do it with a primary constructor. After that, we showed how to use a secondary constructor with default values.

As always, the source code of the examples is available over on GitHub.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.