Java Record Derived Creation (stopgap until JEP 468 arrives)
Java 14 (in a preview feature) introduced Records. In a nutshell: Records are (mostly) immutable objects with a greatly reduced amount of boilerplate code requirements. For a detailed introduction head over to Baeldung.
When records need update
The short answer: create a new record and use the existing as input. Let's look at an example:
public record Billionaire(String name, Long wealth, Temporal assessment) {
public Billionaire cloneWithNewAssesment(Long newWealth, Temporal currentAssesment) {
return new Billionaire(this.name, newWealth,currentAssesment);
}
}
By itself this is a clean solution. You might add another function for unchanged assesment values. It gets messy when your records have a few more fields.
To address this, JEP 468 has neen proposed. Unfortunately it isn't seen anywhere in JDK 23 or JDK 24. Its syntax follows the spirit of boilerplate avoidance.
// Wealth changed
Billonaire theUpdated = oldBillionaire with { newWealth, newAssesment}
// Wealth unchanged
Billonaire anotherUpdated = oldBillionaire with { newAssesment}
Ultimately that's the way to go. Until then I needed a stopgap measure. It contains quite some boilerplate, following the builder pattern to make use easier
public record Billionaire(String name, Long wealth, Temporal assessment) {
public BillionaireUpdater forCloning() {
return new BillionaireUpdater(this);
}
}
public class BillionaireUpdater {
Long wealth = null;
Temporal assessment = null;
final Billionaire old;
public BillionaireUpdater(Billionaire old) {
this.old = old;
}
public BillionaireUpdater wealth(Long wealth) {
this.wealth = wealth;
return this;
}
public BillionaireUpdater assessment(Temporal assessment) {
this.assessment = assessment;
return this;
}
public Billionaire build() {
return new Billionaire(
old.name(),
this.wealth == null ? old.wealth : this.wealth,
this.assesment == null ? old.assesment : this.assesment
);
}
}
This approach keeps the "bulky" code outside the record, so once JEP 468 becomes available, updating should be managable leading to the ultimate removal of the Updater
classes. The use is quite straight forward:
Billionaire theUpdated = oldBillionaire.forCloning()
.wealth(insaneAmount)
.assesment(dateOfAssesment)
.build();
As usual YMMV
Posted by Stephan H Wissel on 30 December 2024 | Comments (0) | categories: Java WebDevelopment