Records in Java (Data-Carrying Classes)

Records in Java (Data-Carrying Classes)

Introduction

In Java programming, we often create classes whose main job is just to carry data — without much behavior (methods) attached to them. These are known as Data-Carrying Classes or POJOs (Plain Old Java Objects).

Traditionally, creating such classes involved a lot of boilerplate code: constructors, getters, setters, toString(), equals(), and hashCode() methods.
Writing and maintaining them manually is time-consuming and error-prone.

Java 14 introduced a powerful feature called Records to solve this problem.

In this post, we'll understand:

  • What Java Records are

  • Why they are useful

  • How to create and use Records

  • Key points and limitations

  • Real-world examples

Let's dive deep!


  



What is a Record in Java?

A Record is a special kind of class in Java designed to hold data.
It automatically provides:

  • A constructor

  • Getters

  • toString()

  • equals()

  • hashCode()

You don't need to manually write these anymore!

In simple words:

A Java Record is a quick, concise way to create an immutable data-carrying class.

Introduced as a preview in Java 14, and became a standard feature from Java 16 onward.


Why Use Records?

Here are some strong reasons to use Records:

  • Less boilerplate code

  • Immutable by default (safer for multithreaded applications)

  • Clear and concise syntax

  • Readable code

  • Encourages best practices for data modeling


Syntax of a Record

The basic syntax looks like this:

record RecordName(Type fieldName1, Type fieldName2, ...) {
}

Example:

record Person(String name, int age) {
}

That simple two-line code automatically creates a Person class with:

  • A constructor

  • name() and age() methods (getters)

  • toString(), equals(), and hashCode()

You can use it like this:

public class RecordExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);
        System.out.println(person.name()); // Alice
        System.out.println(person.age());  // 30
        System.out.println(person);        // Person[name=Alice, age=30]
    }
}

Key Features of Records

  • Immutable: All fields are final; you can't change them after creation.

  • Compact: Reduces boilerplate code drastically.

  • Automatic Method Generation: Constructor, toString(), equals(), hashCode(), and field getters.

  • Inheritance: Records cannot extend other classes because they implicitly extend java.lang.Record.

  • Implements Interfaces: Records can implement interfaces.


Customizing a Record

You can add extra methods inside a Record if needed.

Example:

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

Usage:

public class CustomRecordExample {
    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle(5, 10);
        System.out.println(rectangle.area()); // 50
    }
}

Important Points to Remember

Point Description
Final Fields Fields are implicitly private and final.
Immutable Object Once created, data cannot be changed.
No Setter Methods Only getter methods are available.
Compact Constructors You can define your own constructor if needed, but must initialize all fields.
Serializable Records are serializable by default.
Cannot Extend Class Records cannot inherit from another class (only interfaces).

Limitations of Records

While Records are super useful, they have some limitations:

  • Not suitable when you need mutable objects.

  • Can't define a Record without fields.

  • No support for field validation without defining a custom constructor.

  • Cannot extend another class (only interfaces can be implemented).


Real-World Example: Using Records for API Response

Imagine you are writing a web service and you need to send a user profile as a response.

Instead of creating a big, verbose class, you can use a Record:

record UserProfile(String username, String email, int age) {
}

Using it:

UserProfile profile = new UserProfile("john_doe", "john@example.com", 25);

System.out.println(profile.username());
System.out.println(profile.email());
System.out.println(profile.age());

This is simple, readable, and maintainable!


FAQs About Java Records

1. Are Java Records mutable?

No, Java Records are immutable by design. All fields are final.

2. Can a Record extend another class?

No, Records cannot extend any class other than java.lang.Record.

3. Can I add methods to a Record?

Yes, you can add custom methods inside a Record.

4. From which Java version are Records available?

Records are officially available from Java 16 onwards.

5. Can Records have static fields and static methods?

Yes, you can define static fields and static methods inside a Record.


Conclusion

Java Records are a fantastic addition to the language, making it easier and faster to create data-carrying classes.
They help reduce boilerplate, improve code readability, and promote immutability — all essential qualities for modern Java applications.

If you haven't tried Records yet, it's time to give them a shot and make your Java codebase cleaner and more efficient!

Happy Coding! 🚀


Previous
Next Post »