ProgrammingJava Developer

What is a record class in Java, what is it intended for, and what are its limitations?

Pass interviews with Hintsage AI assistant

Answer.

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:

  • Immutability: fields are final, values are set only through the constructor.
  • Automatic generation of standard methods.
  • Cannot inherit from other classes (except Object); can implement interfaces.

Tricky Questions.

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.

Common Mistakes and Anti-Patterns

  • Trying to make fields mutable — syntax will not allow it.
  • Creating complex logic within a record, violating the idea of simple "data containers".
  • Using records where a regular class with behavior is needed.

Real-Life Example

Negative Case

Using long POJOs for each request/response, with manually written equals, hashCode, toString, constructors, and getters.

Pros:

  • Complete implementation flexibility.

Cons:

  • A lot of code.
  • High risk of making an error.

Positive Case

Converting all DTOs to record classes:

public record UserDTO(String login, String email) {}

Pros:

  • Minimal code.
  • Automatically correct equals/hashCode.
  • Hard to make a mistake in implementation.

Cons:

  • If a mutable object or specific logic is required — record is not suitable.