← Back to Blog

Java Records Explained

December 23, 2025

Introduced in Java 14 as a preview feature and finalized in Java 16, Records are a game-changer for writing cleaner, more concise Java code. They provide a compact syntax for declaring classes that are transparent holders for shallowly immutable data.

The Problem with POJOs

Before Records, creating a simple data carrier class (POJO) required a lot of boilerplate:

public class Person {
    private final String name;
    private final int age;

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

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

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

The Record Solution

With Records, the same class can be defined in a single line:

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

What You Get for Free

When you define a record, the compiler automatically generates:

  1. Private final fields for all components.
  2. Public accessor methods (e.g., name() and age()). Note: no get prefix!
  3. Canonical Constructor with the same arguments as the record header.
  4. equals() and hashCode() implementations.
  5. toString() method that prints the record's name and its components.

Customizing Records

You can still customize records if needed. For example, validating data in the constructor:

public record Person(String name, int age) {
    // Compact constructor
    public Person {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
}

When to Use Records

  • DTOs (Data Transfer Objects): Perfect for carrying data between layers.
  • Map Keys: Since equals and hashCode are automatically reliable.
  • Stream Processing: ideal for temporary data structures in streams.

Records are immutable by default, making them thread-safe and less error-prone. They signal to other developers that "this class is just data."