What is Record and how does it help create immutable classes?
One line instead of 20+. Automatically:
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()— notgetX()) 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
instancefields 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:
finalclass,private finalfields, constructor, getters (name()notgetName()), 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]]