Hi there. I am in the process of converting a large Java code base to Kotlin, and I’ve run into an issue that makes this transition less than smooth. I’d like to suggest a small change to how class constructors work, particularly for data classes.
As an example, I have a Java class like this:
class MyClass {
String name;
List<String> addresses;
public MyClass(String name, List<String> addresses) {
this.name = name == null ? "" : name
this.addresses = addresses == null ? Collections.emptyList() : addresses
}
The idea here being that when a constructor parameter is null, we substitute a non-null default.
Kotlin can’t quite do this without either a deferred init, lazyinit, secondary constructor, or a companion object overriding the invoke
operator. And with data classes, the first two options don’t appear possible.
data class MyClass(
val name:String? = "",
val addresses: List<String>? = emptyList()
)
In this case, I will only get my default value if the parameter is not specified at all, but if the input to the parameter is null
, then the field becomes null
. If I make the fields non-nullable, then existing Java code that calls this constructor hits NullPointerException where it didn’t before. (For example, a serialization library such as Jackson or Kryo can cause breakages, particularly in an environment where different versions of running code have to be able to talk to each other.)
It would be really convenient to have some way to apply the default value to a constructor field WHEN the input is null, and not just when it’s not provided. Something like:
data class MyClass(
val name: String ?: "",
val addresses: List<String> ?: emptyList()
)
The intent here is that the field inside the class is non-nullable (String
, not String?
), but the parameter can accept null and assign a default to the field.
Also, I know that I can use @JvmOverloads
to create versions of the constructor with varying parameters, but (a) this doesn’t address the issue since existing calls use the full constructor anyway, and (b) our code base has data classes with a dozen or more fields, so creating permutations of the constructor is not in any way practical.
TL;DR: Please add a syntax to constructor field declarations that allows the constructor to assign a default value to a field when the value provided for the parameter is null. This will simplify the creation of data classes without requiring workarounds like overriding the invoke
operator.
Thanks!