Beyond records - construction vs re-construction
Remi Forax
forax at univ-mlv.fr
Tue Jan 20 08:56:32 UTC 2026
Hello,
the JEP 468 proposes a mechanism by which a new record instance can be derived from an existing one,
one problem of proposing that feature as a building block is that we know that people will abuse it to use to create a record from an empty record.
Instead of fighting that, for me it shows that the reconstruction proposed by JEP 468 is not the right building block.
As state by Brian in the recond mail "Data oriented programmaing - Beyond records",
the carrier syntax provides a state decription and it can be used not only to reconstruct an instance but also simply to construct an instance.
For the rest of this mail, i will use the following class as an example
final class MutablePoint(int x, int y) {
private int x, y;
public Point() { this.x = x; this.y = y; super(); }
public int x() { return x; }
public void x(int x) { this.x = x; }
public int y() { return y; }
public void y(int y) { this.y = y; }
}
*Construction*
Currently Java the only way to create an instance is to call the constructor in a positional way
var point = new MutablePoint(0, 0);
For a carrier class, given that we have a state description, the idea is to introduce an instance construction based on states
With each state being explicitly initialized.
For example using a made-up syntax
var point = MutablePoint { x = 0, y = 0 };
This is not new, most languages already have this kind of syntax (C, JavaScript, Rust etc) and we now that this is a missing piece in Java,
because people goes as far a writing one builder class per data class for that.
Ì believe this is our building block to also re-construct instance.
*Re-construction*
The idea is that instead of providing an expression for all states, we add a way to complement using states on an already existing instance.
again, not a new idea, something similar is done in JavaScript or Rust.
Using our made-up syntax, we get something like this
var point1 = MutablePoint { x = 1, y = 2 };
var point2 = MutablePoint { x = 2, ...point1 };
with point2.x equals to 1 and point2.y equals to 2 (the value of point1.y).
It is also useful for transferring state between two different classes, by example, a mutable point and an immutable one.
List<MutablePoint> mutablePoints = ...
record Point(int x, int y) { }
var points = mutablePoints.stream().map(p -> Point { ...p }).collect(Collectors.toSet());
Obviously, the exact semantics has to be flesh out but i think this kind of construction semantics is more general and easier to understand thus a better building block than what is proposed by JEP 468 *.
regards,
Rémi
* for the defence of JEP 468, using a mutable like syntax for reconstruction did made more sense when the proposed deconstruction syntax was also using a mutable like syntax.
More information about the amber-spec-experts
mailing list