History of the Question:
Record classes (record) appeared in Java 14 as a preview, and since the release of Java 16, it has been stable functionality. They implement the concept of immutable containers for storing data, similar to value objects. This is a reaction to the verbosity of classic DTOs and POJOs in Java.
Problem:
For simple data objects, it was necessary to manually implement constructors, equals(), hashCode(), toString(). This is a routine, error-prone task that takes up many lines of code.
Solution:
A record class is declared in one line and automatically gets a constructor, getters, equals(), hashCode(), toString(). Record fields are immutable (final), and records are particularly useful for passing information between application layers.
Example code:
public record Point(int x, int y) {} Point p = new Point(3, 5); System.out.println(p.x()); // 3 System.out.println(p); // Point[x=3, y=5]
Key features:
Can the state of a record object be changed after its creation?
No — all fields are final, and their values cannot be changed in any way.
Can a record be created with non-standard logic in the constructor?
Yes, a compact or regular constructor can be defined and checks can be added:
public record Point(int x, int y) { public Point { if (x < 0 || y < 0) throw new IllegalArgumentException(); } }
Can a record be abstract or inherit fields/logics from other classes?
No — a record is always final. It can implement interfaces, but cannot inherit classes, except for Object.
Using long POJOs for each request/response, with manually written equals, hashCode, toString, constructors, and getters.
Pros:
Cons:
Converting all DTOs to record classes:
public record UserDTO(String login, String email) {}
Pros:
Cons: