Question 20 · Section 13

What is Record and how does it help create immutable classes?

One line instead of 20+. Automatically:

Language versions: English Russian Ukrainian

Junior Level

Record is a special type of class in Java (introduced in Java 14, stable from Java 16) that automatically creates an immutable class for holding data.

Before Record

public final class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }

    @Override public boolean equals(Object o) { ... }
    @Override public int hashCode() { ... }
    @Override public String toString() { ... }
}

With Record

public record Point(int x, int y) {}

One line instead of 20+. Automatically:

  • Class is final
  • Fields are private final
  • Constructor
  • Getters (x(), y() — not getX())
  • equals(), hashCode(), toString()

Middle Level

What the compiler does for you

public record User(String name, int age) {}

Generates:

public final class User extends java.lang.Record {
    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String name() { return name; }
    public int age() { return age; }

    // equals, hashCode, toString — across all fields
}

Shallow immutability

record guarantees that references won’t change. But if a field is a mutable collection, its contents can be modified:

public record Order(Long id, List<String> items) {}

Order order = new Order(1L, new ArrayList<>(List.of("A")));
order.items().add("B"); // POSSIBLE! items — the same list

Solution — compact constructor

public record Order(Long id, List<String> items) {
    public Order {
        items = List.copyOf(items); // defensive copy
    }
}

When to use

  • DTO — data transfer between layers
  • Map keys — stable hashCode
  • Local structures — temporary tuple storage

Senior Level

Limitations

  • Cannot extend other classes (already extends java.lang.Record)
  • Cannot be a base class (always final)
  • Cannot have instance fields besides those declared in the header
  • Cannot be abstract

Record vs Lombok @Value vs regular final class

  Record Lombok @Value Final class
Boilerplate Minimal Minimal Manual
Inheritance No Possible Possible
Extra fields No Possible Possible
Dependencies JDK Lombok None

Compact constructor and validation

public record User(String email, int age) {
    public User {
        Objects.requireNonNull(email, "Email required");
        if (age < 0) throw new IllegalArgumentException("Age must be positive");
    }
}

Custom methods

public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }
}

Summary for Senior

  • record — a special language construct for immutable value classes. This is not just sugar — records have their own limitations (cannot inherit, cannot have instance fields besides declared).
  • Radically reduces code volume and the chance of errors in equals/hashCode
  • Manual collection copying is still necessary
  • Use for DTOs, Map keys, temporary structures
  • Cannot participate in inheritance hierarchies

Interview Cheat Sheet

Must know:

  • Record (Java 14+, stable Java 16) — special language construct for immutable value classes
  • Automatically: final class, private final fields, constructor, getters (name() not getName()), equals/hashCode/toString
  • Shallow immutability: references are immutable, but mutable collections can be modified
  • Compact constructor: public Order { items = List.copyOf(items); } — for defensive copying
  • Limitations: no inheritance, no extra instance fields, no abstract
  • Record vs Lombok @Value: Record — JDK, no dependencies; Lombok — more flexibility

Frequent follow-up questions:

  • Does Record deep copy collections? — No, only shallow; need to do it manually in the compact constructor
  • Can you add a field to a Record? — No, only those declared in the header
  • Can Record be inherited? — No, always final; cannot be a base class
  • Are getters in Record getX()? — No, just x() — no get prefix

Red flags (do NOT say):

  • “Record is fully immutable” — collections need to be copied manually
  • “Record can be extended” — always final, no inheritance
  • “Record replaces Lombok” — Lombok @Builder, @Singular give more functionality
  • “Record is just sugar” — records have their own limitations and semantics

Related topics:

  • [[1. What is an immutable object]]
  • [[3. How to create an immutable class in Java]]
  • [[26. How to implement Builder pattern for an immutable class]]
  • [[27. Can you use immutable objects as keys in HashMap]]
  • [[29. How to properly work with collections in immutable classes]]