Historia pytania:
Klasy record (record) pojawiły się w Javie 14 jako podgląd, a od wydania Javy 16 są stabilną funkcjonalnością. Realizują koncepcję niemutowalnych (immutable) kontenerów do przechowywania danych, podobnych do obiektów wartości (value-objects). Jest to odpowiedź na rozwlekłość klasycznych DTO i POJO w Javie.
Problem:
Dla prostych obiektów z danymi trzeba było ręcznie implementować konstruktory, equals(), hashCode(), toString(). To rutynowa, podatna na błędy praca, zajmująca wiele linii kodu.
Rozwiązanie:
Klasa record jest deklarowana w jednej linii i automatycznie otrzymuje konstruktor, gettery, equals(), hashCode(), toString(). Pola record są niemutowalne (final), rekordy są szczególnie przydatne do przesyłania informacji między warstwami aplikacji.
Przykład kodu:
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]
Kluczowe cechy:
Czy można zmienić stan obiektu record po jego utworzeniu?
Nie — wszystkie pola są final, nie można zmienić wartości w żaden sposób.
Czy można tworzyć recordy z nietypową logiką w konstruktorze?
Tak, można zdefiniować konstruktor kompaktowy lub standardowy i dodać sprawdzenia:
public record Point(int x, int y) { public Point { if (x < 0 || y < 0) throw new IllegalArgumentException(); } }
Czy record może być abstrakcyjny lub dziedziczyć pola/logikę od innych klas?
Nie — record zawsze jest finalny. Może implementować interfejsy, ale nie może dziedziczyć klas, poza Object.
Użycie długich POJO dla każdego zapytania/odpowiedzi, z ręcznym pisaniem equals, hashCode, toString, konstruktorów i getterów.
Zalety:
Wady:
Przeniesienie wszystkich DTO do klas record:
public record UserDTO(String login, String email) {}
Zalety:
Wady: