Records: compact constructors, generated equals/hashCode/toString
A record auto-generates a canonical constructor, accessors (x(), not getX()), equals/hashCode
(component-wise), and toString(). A compact constructor (no parameter list) lets you validate/normalize
arguments before they're assigned to the (implicitly final) fields.
record Point(int x, int y) {}
Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);
System.out.println("p1.equals(p2) [value equality]: " + p1.equals(p2));
System.out.println("p1 == p2 [reference identity]: " + (p1 == p2));
System.out.println("toString(): " + p1);
System.out.println("accessor (not getX()): " + p1.x() + "," + p1.y());
record Positive(int v) {
public Positive {
if (v <= 0) throw new IllegalArgumentException("v must be positive, got " + v);
}
}
try {
new Positive(-3);
} catch (IllegalArgumentException e) {
System.out.println("compact constructor validation fired: " + e.getMessage());
}
A real JLS rule this surfaces: the compact constructor's access modifier must exactly match the
record's own declared access level -- not weaker, not stronger. A public record needs an explicit public
on its compact constructor; leaving it off is a compile error, verified below (captured verbatim from a real
javac run on a top-level public record PubRec(int v) { PubRec { ... } }):
PubRec.java:2: error: invalid canonical constructor in record PubRec
PubRec {
^
(attempting to assign stronger access privileges; was public)
1 error