Goodbye Boilerplate: Simplifying Java Objects with Records

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
privatefinalfield with the same name and declared type you’ve choseThe 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 beage()A public constructor with all the fields
Equals,hashCode, andtoStringimplementations (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!




