What are Java records, and what problem do they solve?
Quick Answer
Records (Java 16+) are a concise way to declare immutable data-carrier classes: from a single declaration, the compiler generates a canonical constructor, private final fields, public accessors, and correct equals()/hashCode()/toString(). They eliminate the verbose, error-prone boilerplate of hand-written value/DTO classes.
Detailed Answer
Before records, a simple immutable data holder required a lot of repetitive, error-prone boilerplate: private final fields, a constructor, getters, and manually-written equals()/hashCode()/toString() — easy to get subtly wrong (e.g., forgetting a field in equals()).
A record (finalized in Java 16) collapses all of that into one declaration:
record Point(int x, int y) { }
This single line generates:
private final int x; private final int y;- A canonical constructor
Point(int x, int y) - Accessor methods
x()andy()(notgetX()— no "get" prefix) - Correct, component-based
equals(),hashCode(), andtoString()
Records can still have additional methods, static members, and a compact constructor for validation:
record Range(int min, int max) {
Range { // compact constructor — validates before fields are assigned
if (min > max) throw new IllegalArgumentException("min > max");
}
int length() { return max - min; }
}
Constraints: all fields are implicitly private final, a record cannot extend another class (it implicitly extends Record), and it cannot declare additional instance fields beyond its components. Records are ideal for DTOs, value objects, and API response/request shapes — anywhere you want a transparent, immutable carrier of data without hand-rolling boilerplate.