Reputation: 7699
I have a record:
public record Thing(
Boolean field1,
EnumType field2,
int field3,
String, field4
. . .
I'm adding new fields to Thing
a lot, which breaks all my code that uses the canonical constructor, and the fields are piling up, which makes the canonical constructor increasingly awkward to use.
What I'd like to do is be able to pass in specific values for arbitrary fields:
new Thing(field3 = 1, field4 = "XXX");
new Thing(field1 = true, field2 = ENUMVALUE);
Now, I know I can do constructors like:
Thing(int i, String s) ...
Thing(Boolean b, EnumType, e) ...
. . .
new Thing(1, "XXX");
new Thing(true, ENUMVALUE);
But it's really a situation of not knowing which fields I want to override the default values for. The only thing I've been able to come up with so far is turning Thing
into a regular object so I can do something like:
new Thing().setField1(true).setField4("Blah");
Which is kind of a bummer because I don't want the values to be mutable once initialized.
Upvotes: 4
Views: 7710
Reputation: 16805
Unfortunately Java does not have named arguments (at least at this point in time). What we can do to overcome this missing language feature is to use the builder pattern.
For records we could do something like this:
public record Thing(Boolean field, int field2, String field3) {
private Thing(ThingBuilder thingBuilder) {
this(thingBuilder.field, thingBuilder.field2, thingBuilder.field3);
}
public static class ThingBuilder {
// We can set default values for the fields
private Boolean field = false;
private int field2;
private String field3 = "";
public ThingBuilder() {}
public ThingBuilder field(Boolean field) {
this.field = field;
return this;
}
public ThingBuilder field2(int field) {
this.field2 = field;
return this;
}
public ThingBuilder field3(String field) {
this.field3 = field;
return this;
}
public Thing build() {
return new Thing(this);
}
}
}
We can build Thing
instances in the following way:
Thing thing = new Thing.ThingBuilder().field(true).field2(2).field3("some string").build();
Also, we can omit some fields and have them use their default values:
Thing thing = new Thing.ThingBuilder().field3("some string").build();
Upvotes: 7