# Goodbye Boilerplate: Simplifying Java Objects with Records

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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741016371724/e89c91fc-087f-4b0c-9ae5-5084b2fd0061.png align="center")

`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:

```java

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:

```java
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](https://github.com/mdjc/blog-posts-app/commit/b32ff9b95deb32653ef50e6b64918e6a75fefa32).

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!**

* [The Java record keyword on Baeldung](https://www.baeldung.com/java-record-keyword)
    
* [Oracle Documentation on Records](https://docs.oracle.com/en/java/javase/21/language/records.html)
