This is the third part of the miniseries about record
s.
It revisits the copy idea introduced in the first part;
this time without resorting to reflection.
Given a Person
record and a demo program that asserts some basic properties.
public record Person(String name, String nickname) {
public static void main(String[] args) {
var person = new Person("Terence", "Nobody");
assert "Terence".equals(person.name());
assert "Nobody".equals(person.nickname());
var mario = new Person("Mario", person.nickname());
assert "Mario".equals(mario.name());
assert "Nobody".equals(mario.nickname());
}
}
As described in Functional transformation of immutable objects, Java might support the following syntax in the future:
var mario = person with { name = "Mario"; }
In the meanwhile, here’s a way to achieve something similar with minimal extra code. It leverages following features, all available since Java 17:
Here’s a line we could write today:
var mario = person.with(new Name("Mario"));
It uses a type with a deliberate chosen name close to its component name.
That’s the underlying code with an update demo program:
public record Person(String name, String nickname) {
public sealed interface Component {}
public record Name(String value) implements Component {}
public record Nickname(String value) implements Component {}
public Person(String name) {
this(name, "");
}
public Person with(Component component) {
return new Person(
component instanceof Name name ? name.value : name,
component instanceof Nickname nickname ? nickname.value : nickname);
}
public Person with(Component... components) {
var copy = this;
for (var component : components) copy = copy.with(component);
return copy;
}
public static void main(String[] args) {
var person =
new Person("Terence")
.with(new Nickname("Nobody"))
.with(new Nickname("Somebody"), new Name("Mario"));
assert "Mario".equals(person.name());
assert "Somebody".equals(person.nickname());
System.out.println(person); // Person[name=Mario, nickname=Somebody]
}
}
with
methods into an interface?Optional<T>
as component types?Collection<T>
as component types?