thecodex.expert · The Codex Family of Knowledge
Java

Records

What used to take 40+ lines of constructor, getters, equals, hashCode, and toString boilerplate now takes exactly one line.

Java 21 LTS Finalized in Java 16 Last verified:
Canonical Definition

A record declares its components in the header, and the compiler automatically generates a canonical constructor, a public accessor method per component (named exactly after the component, not prefixed with "get"), plus correctly-implemented equals, hashCode, and toString — all fields are implicitly final, making a record's instances immutable by design. This targets the extremely common "plain data holder" class, which previously required substantial repetitive boilerplate to implement correctly.

One line replaces dozens

This single line generates everything a traditional immutable data class would need — a constructor, x() and y() accessors (note: no "get" prefix), equals/hashCode comparing by value, and a readable toString.

JavaPoint.java
public record Point(double x, double y) { }

Point p = new Point(3.0, 4.0);
System.out.println(p.x());          // 3.0 — accessor, not getX()
System.out.println(p);               // Point[x=3.0, y=4.0] — auto-generated toString

Point p2 = new Point(3.0, 4.0);
System.out.println(p.equals(p2));   // true — compares by VALUE, not reference

Records can still have methods and validation

A compact canonical constructor lets you add validation logic without repeating the parameter list — assignment to the fields still happens automatically after the compact constructor body runs.

JavaRange.java
public record Range(int min, int max) {
    public Range {   // compact constructor — no parameter list repeated
        if (min > max) {
            throw new IllegalArgumentException("min must be <= max");
        }
    }

    public int length() {   // records CAN have additional methods
        return max - min;
    }
}

Records are still classes, with real limitations

A record implicitly extends java.lang.Record, so it cannot extend any other class (though it can implement interfaces); every field is implicitly final; and records are specifically for the immutable-data-holder case, not a general-purpose class replacement — a class needing mutable state or a class hierarchy still needs a regular class.

Sources

1
Oracle. Java Language Specification, "Record Classes," docs.oracle.com/en/java/javase/25/language/records.html, and JEP 395 — Records.