Unravel โบ Java concepts โบ OOP and types
Records
A record is a compact class for plain data: you list the fields once and Java generates the constructor, getters, equals, hashCode and toString.
At a glance
A labelled form with fixed boxes.
- 1record Point(int x, int y) {} creates a final class with private final fields, a constructor, accessors x() and y(), and value-based equals, hashCode and toString
- 2A compact constructor lets you validate: Point { if (x < 0) throw new IllegalArgumentException(); }
- 3Records can have static methods, extra methods and implement interfaces, but cannot extend a class or add instance fields
- 4Because equals and hashCode compare all components, records work well as keys in a Map or elements of a Set, and as the immutable messages passed between threads or sent over Kafka
- 5Since Java 21 a record can be taken apart in a pattern: if (obj instanceof Point(int x, int y)) { ..} or in a switch, giving you the components as variables without calling the accessors.
- Records are shallowly immutable: a record holding a List still lets the list change unless you copy it with List.copyOf in the constructor
- The compiler generates the members, and equals, hashCode and toString are implemented with invokedynamic (ObjectMethods)
public record Money(BigDecimal amount, String currency) { public Money { if (amount.signum() < 0) { throw new IllegalArgumentException("negative amount"); } } public Money plus(Money other) { return new Money(amount.add(other.amount), currency); }}Read the full explanation (about 1 min)
A record is a compact class for plain data: you list the fields once and Java generates the constructor, getters, equals, hashCode and toString.
A mental model
A labelled form with fixed boxes. Once filled in, it cannot be edited, and two forms with identical contents are considered equal.
How it works
record Point(int x, int y) {} creates a final class with private final fields, a constructor, accessors x() and y(), and value-based equals, hashCode and toString.
A compact constructor lets you validate: Point { if (x < 0) throw new IllegalArgumentException(); }.
Records can have static methods, extra methods and implement interfaces, but cannot extend a class or add instance fields.
Because equals and hashCode compare all components, records work well as keys in a Map or elements of a Set, and as the immutable messages passed between threads or sent over Kafka.
Since Java 21 a record can be taken apart in a pattern: if (obj instanceof Point(int x, int y)) { ... } or in a switch, giving you the components as variables without calling the accessors.
Going deeper
Records are shallowly immutable: a record holding a List still lets the list change unless you copy it with List.copyOf in the constructor. They suit DTOs, API responses, map keys and messages, but not JPA entities.
Under the hood
The compiler generates the members, and equals, hashCode and toString are implemented with invokedynamic (ObjectMethods). The class extends java.lang.Record.
Common mistakes
- Assuming deep immutability.
- Using a record as a JPA entity.
How Unravel recognises it
When you paste code, Unravel looks for these signs of records. Spotting them yourself is a good habit when you read unfamiliar code:
- Language constructs:
record
Part of a learning path
- Modeling data in modern Java ยท previous: Lombok annotations ยท next: equals() and hashCode()
Related concepts
Builds on this
Frequently asked questions
What is Records?
A record is a compact class for plain data: you list the fields once and Java generates the constructor, getters, equals, hashCode and toString.
What are the most common mistakes with Records?
Assuming deep immutability. Using a record as a JPA entity.
How can I see Records in real code?
Paste your own Java into Unravel and it will point out where records appears, explain how it works at the detail level you choose, and draw the flow of the code around it.