Using Kotlin named parameters constructor from Java

When incrementally introducing Kotlin to an existing Java codebase, is there any way to make use of Kotlin named parameters from Java?

I know that the Java language doesn’t support named parameters, but is there any kind of workaround? Something that could generate Builder-pattern code based on the Kotlin constructor with named parameters. Then Java client code could use this Builder pattern code to construct instances of the Kotlin data class.

Did you try? It should generate overloads with default values.

@JvmOverloads

Thanks for the suggestion. Unfortunately, while @JvmOverloads does allow default values to be used, what I am looking for is the ability to actually specify the parameter names when constructing an instance of the class. It’s necessary when you have more than 2 or 3 parameters to a function.

Otherwise you end up with constructor calls in Java that have 10+ arguments and it’s error-prone & hard to maintain. IDEA does help with its nice parameter name hints, but in order to sell my team on Kotlin, it would be really helpful to be able to eliminate our Builder pattern boilerplate and still have clear & robust construction of objects.

Maybe it just isn’t possible, and we’ll have to wait until we can convert our calling code as well as the data classes to Kotlin.

1 Like

There is no concept of named parameters in Java, so you cannot use that kind of feature.

The closest solutions I see is to bind properties to a map, which, from java, would allow you to hack things like that:

var myValue = new MyDataClass(Map.of("prop1", "valueForProp1", "prop2", "valueForProp2", ...);

that looks very ugly to me…

However, I see this as a last resort for corner-cases where you’re forced to use a map as a datasource, and that’s all. Using this as a primary solution to “simulate” named parameters feels very wrong to me, because it breaks type-safety.

Now, even in Java 17 with records, you’re forced to use Lombok if you want to reduce boiler-plate while keeping type-safety. This is, from my point of view, a great advantage of Kotlin. A lot of “tiny” features combine to provide a great experience with data modeling : properties first, named and default arguments, null-safety in types, data classes, sealed classes, etc, combined property/constructor definition, syntax for anonymous object declaration, etc.

1 Like

In one of the Java Spring Boot project we’ve introduced Kotlin for several reasons, one of which was to get away from Builder pattern. But introducing Kotlin case classes with default values and named parameters is not enough. What we did, we’ve added mapper classes written in Kotlin. This gave us an ability to use named parameters in case classes constructors and provided nice interface to be used in Java code.

In Java we had REST controllers which were using Kotlin case classes as DTOs (request and response objects) and services and repositories also written in Java using entity Java classes. We’ve injected Kotlin mappers into Java controllers and services and called only mapper.map methods. All construction was done in Kotlin code.

Eventually we’ve moved to Kotlin completely in this project at the end.

2 Likes

That sounds interesting.

By “Kotlin case classes”, I assume you mean “data classes”?

What is the “mapper class” like? Is it basically the Builder pattern implemented in Kotlin to build a certain DTO class, for use by Java code?

1 Like

Yes, of cause data classes I meant.

Mappers are responsible for mapping between DTO and Entity classes.
For example we have PersonEntity class, like this:

public class Person {
  private final String firstName;
  private final String lastName;
  private final Integer age;
  
  // all args constructor
  // getters
  // equals(), hashCode() etc 
}

and PersonDTO Kotlin class:

data class PersonDTO(val firstName: String, val middleName: String? = null, lastName: String, age: Int)

Mapper will convert one class to another, like this:

class PersonMapper {
    fun map(person: PersonEntity): PersonTO = PersonTO(
        firstName = person.firstName, // null checks with either exception or default value
        lastName = person.lastName,
        age = person.age)
}

This is oversimplified code, but the idea is to have code dealing with creation of Kotlin classes using constructor with named parameters in some Kotlin class with some simple functions with fewer parameters. We’ve used mapper classes, but it could be factory functions or builder or something similar.

2 Likes