Core JavaJava 16

Explaining the Record Class in Java

Posted On
Posted By Reshma Bidikar

With every release, Java introduces new features that enhance the language’s capability and make it more developer-friendly. One of the most notable additions in Java 14 (and made stable in Java 16) is the Record class. The Record class simplifies the creation of immutable data objects, making code more concise and readable.

What is a Record Class?

A Record in Java is a special kind of class that is used to model immutable data. Unlike regular classes, Records are designed to be concise and automatically handle common methods like equals(), hashCode(), and toString().

You can define a Record as follows:

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

This single line of code does a lot:

  • It declares a new record type Point.
  • It defines two fields, x and y, which are implicitly private and final.
  • It automatically generates a constructor, and accessor methods (like x() and y()), and implementations for equals(), hashCode(), and toString().

Key Features of Records

Immutability

Records are inherently immutable, meaning their fields cannot be changed once an instance is created. This immutability is enforced by the fact that all fields in a Record are implicitly final.

Conciseness

Records reduce boilerplate code. You don’t need to manually write constructors, getters, equals(), hashCode(), or toString() methods. This makes the code cleaner and less error-prone.

Component Accessors

The fields in a Record class are called “components,” and Java automatically generates accessor methods for them. These methods have the same name as the component. For example, in the Point record, you can retrieve the x and y values using x() and y() methods, respectively.

Custom Methods and Constructors

While Records are designed to be simple, you can still add custom methods and constructors if needed.                       However, the primary constructor (the one that takes all components as parameters) is always generated                       automatically

public record Point(int x, int y) {
  public Point {
    if (x < 0 || y < 0) {
      throw new IllegalArgumentException("Coordinates cannot be negative");
    }
  }
}
In this example, a custom constructor is defined to enforce a validation rule

Limitations of Record Class

Inheritance not supported

Records cannot extend other classes. They implicitly extend java.lang.Record, which is a sealed class. However, Records can implement interfaces.

No-arg constructors

Records do not have a no-argument constructor by default. If you need to create an instance of a Record with default values, you’ll need to define those explicitly in the primary constructor or provide a static factory method.

Immutability Constraints

Since all fields in a Record are final, if you have mutable fields (like an array or a list), the immutability guarantee only applies to the reference, not the object it points to. If you need truly immutable collections, consider using classes from libraries like Guava or using List.of() for unmodifiable lists.

 

Use Cases for Record Class

Records are best suited for modeling simple data carriers or value objects where the primary concern is the data they encapsulate. Here are some common use cases:

  1. DTOs (Data Transfer Objects):
    When transferring data between layers of an application or across network boundaries, Records offer a simple way to encapsulate the data.
  2. Configuration Settings:
    Immutable configuration settings can be modeled effectively with Records, ensuring that configuration values cannot be modified after they are set.
  3. Responses from APIs:
    When receiving data from an API, especially in RESTful services, Records can be used to represent the structure of the data received.
  4. Event Data in Event-Driven Systems:
    Events in event-driven architectures can be modeled as Records, ensuring that the event data remains immutable and easy to work with.

Conclusion

By reducing boilerplate and promoting immutability, Records help developers focus on the core logic of their applications rather than the repetitive and error-prone task of writing getter methods, constructors, and toString() implementations. Whether you’re modeling data transfer objects, configuration settings, or simple value objects, Records provide a powerful and concise way to handle data in Java.

If you'd like to watch a detailed video tutorial of this topic or other related topics, do check out my Java course here

Also, if you'd like to test your Java knowledge, do check out my practice tests course here


If you like this post, please do let me know via the comments box below.  You can also connect with me via my Facebook Page or subscribe to my Youtube channel!

Related Post