Records instead of named parameters

  • Post category:Java

Actually there is an existing agreement that renaming of method parameters is without consequence. Specific transforms are called out in JLS as binary compatible.

Brian Goetz

I had already mentioned my concern about the strong coupling that named parameters introduce in the first revisited post. Even though the coupling is just a strong as when a custom class is used as a parameter, developers simply do not expected this coupling on named parameters. But the fact that the specification defines that renaming parameters names are to be without consequence, makes named parameters a dead end.

And also because something else has changed since 2013… EDI’s:

And that makes the price to pay for adding named parameters not worth it.

That said, it still was fun to let the idea run through one’s head. And likewise it also is fun to see if there is a way to make this work without renaming parameters… What about using the recently added record classes? Consider this a little creative piece of code (aka it will not compile):

public Rectangle(record Parameters(int width, int height) p) {
    this(p.width(), p.height();
}

new Rectangle(new Parameters(100, 200));

Defining an inline record as a parameter is an easy way to circumvent the rules that apply to parameter names. But the call still is not very readable. Exactly because of that, one of the things that records IMHO have been missing are builders. These could be generated by the compiler as part of a record, or some Maven plugin could be convinced to do that.

public Rectangle(record Parameters(int width, int height) p) {
    ...
}

new Rectangle(Parameters.builder().width(100).height(200).build());

More readable, yes, but it also introduces a lot of scaffolding. Maybe it is better to look at double brace initialization, combined with a little inspiration picked up from a post of mr Goetz in project Amber.

public Rectangle(record Parameters(int width, int height) p) {
    ...
}

new Rectangle(new Parameters(){{width = 100; height = 200;}});

And then with a little compiler tuning the Parameter class can be made anonymous and inferred.

public Rectangle(record(int width, int height) p) {
    ...
}

new Rectangle({{width = 100; height = 200;}});

By adding in a shortcut notation for default values, it is possible to solve the mandatory / optional parameters.

public Rectangle(record(int width = 300, int height) p) {
    ...
}

new Rectangle({{height = 200;}});

That’s close enough to named parameters for me. 🙂

Leave a Reply