Enhanced JEP 395: Records (Standardized)

Java 16 introduced JEP 395: Records as an incubated feature, and with Java 17, this feature was standardized. Records provide a new way to model immutable data structures with less boilerplate code. They are a special type of class designed to hold data without needing the user to write code for typical methods such as constructors, getters, equals(), hashCode(), and toString().

The main goal of Records is to simplify code by automatically providing the standard functionality required for simple data-carrying classes, such as value objects or data transfer objects (DTOs).

What Are Records?

A Record in Java is a special kind of class that primarily focuses on storing immutable data. It is designed to reduce the verbosity of creating simple POJOs (Plain Old Java Objects).

Before records, developers had to manually write the following for a simple data object:

  • A constructor to initialize the fields.
  • Getter methods to access the fields.
  • equals() and hashCode() methods to compare instances.
  • toString() method to provide a string representation of the object.

With records, Java automatically generates all of these methods for you.

Syntax of Records

A record is defined using the record keyword:

public record Person(String name, int age) { }Code language: JavaScript (javascript)

In the above example:

  • Person is a record with two fields: name (a String) and age (an int).
  • Java automatically provides a constructor, getters, equals(), hashCode(), and toString() methods.

You can also define additional methods and customize some behavior within the record if needed.

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 obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}Code language: PHP (php)

Java 17 Record:

<strong>public record Person(String name, int age) { }</strong>Code language: HTML, XML (xml)

Notice how the record definition is significantly more concise, with no need to write getters, constructors, equals(), hashCode(), or toString(). Java automatically provides these methods when the record is compiled.

Additional Capabilities

While records are designed for simplicity, they still offer flexibility and can be extended in the following ways:

  1. Custom Methods: You can define custom methods within a record to implement specific behavior.

public record Person(String name, int age) {
    public String greet() {
        return "Hello, my name is " + name;
    }
}Code language: JavaScript (javascript)

     2.Custom Constructors: You can also define a custom constructor if you need some additional logic when creating the

       record instance.

public record Person(String name, int age) {
    public Person {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
}Code language: PHP (php)

  3.   Implements Interfaces: Records can implement interfaces just like regular classes.

public record Person(String name, int age) implements Comparable<Person> {
    @Override
    public int compareTo(Person other) {
        return this.age - other.age;
    }
}Code language: JavaScript (javascript)

Benefits of Records

Benefit Explanation
Less Boilerplate Records generate methods like toString(), equals(), and hashCode() automatically, reducing repetitive code.
Immutable Fields in a record are final by default, which ensures immutability and thread-safety.
Compact Syntax A record definition is much more compact and concise compared to a traditional class.
Pattern Matching Ready Records are designed with future features like pattern matching in mind. This allows for simpler checks when deconstructing data types.

Limitations of Records

  1. Immutability: Since fields are implicitly final, you cannot change them once the record is created. This can be a limitation when mutable data is needed.
  2. No Inheritance (Extending other classes): Records cannot extend other classes, although they can implement interfaces.
  3. No setters: Records don’t have setters because their fields are immutable.

The standardization of JEP 395: Records in Java 17 provides developers with a simple, concise, and immutable data structure. This feature significantly reduces boilerplate code, making Java applications more maintainable, especially when dealing with data transfer objects (DTOs) or value objects. Records are a great fit for use cases where immutability is essential, and Java 17’s standardization means this feature will be available for widespread use in production applications.

Scroll to Top