Skip to main content

Command Palette

Search for a command to run...

Goodbye Boilerplate: Simplifying Java Objects with Records

Updated
2 min readView as Markdown
Goodbye Boilerplate: Simplifying Java Objects with Records
M

I’m a backend software engineer with over a decade of experience primarily in Java. I started this blog to share what I’ve learned in a simplified, approachable way — and to add value for fellow developers. Though I’m an introvert, I’ve chosen to put myself out there to encourage more women to explore and thrive in tech. I believe that by sharing what we know, we learn twice as much — that’s precisely why I’m here.

As Java Developers, we’ve created many simple classes (with a list of fields, getters, and setters) to represent an object or a subset of it. Most of the time we also need to override the toString, equals, and hashcode methods. Although IDEs can help you generate boilerplate code to expedite the creation of these objects, it’s still repetitive and not fun.

Java records are a new feature introduced in Java 14 (with further improvements in version 16) to create simple Immutable Java Objects compactly using the keyword record.

Here’s an example of a normal class vs a record:

Note: the difference in the declaration with the attributes between parenthesis directly following the name of the class.

Then you can instantiate your record as you would normally do:


NewPostDto dto = new NewPostDto(“A sample title“, “sample content“);

What you get with a record class:

    • A private final field with the same name and declared type you’ve chose

      • The appropriate accessors but with a subtle difference, they match the name of the field, so if you have a field named age, the accessor will be age()

      • A public constructor with all the fields

      • Equals, hashCode, and toString implementations (that used the fields you’ve declared)

Within a record, you can:

  • Declare static fields

  • Declare instance methods

  • Use annotations

  • Change the default implementations that are generated for you for accessors and overridden methods

  • Declare a compact constructor

Within a record, you cannot:

  • Declare instance fields

  • Declare native methods

Compact constructor:

You can create compact constructors within a record to add validations. Compact constructors are only permitted inside record classes because fields are implicitly assigned based on the declared components.

For example:

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

Conclusion

Java records provide a concise and immutable way to define data-holding classes, eliminating boilerplate code for constructors and common methods. While they have some limitations, they are perfect for DTOs simple data models, and other immutable structures.

I recently removed boilerplate from my DTOs using records, you can follow along here.

If you are still using traditional classes for these cases, consider refactoring with records to simplify your code.

Check out the links below to learn more!

More from this blog

Code Like a Woman

40 posts

Code, learnings, and experiences from a Latina in tech.