I think all of us (Java developers and architects alike) have already heard and some of us have used Java record type which has been introduced in a recent version of JDK. In this article, I will present my viewpoint concisely on this topic hoping that it helps someone but please feel free to share your comment / feedback !!.
In my opinion, Java records are a welcome introduction to the java eco-system as other JVM languages like Scala and Kotlin had similar concept (Case class in Scala and data class in Kotlin) for sometime. For sure, records are going to help us reduce / remove boilerplate code from the DTOs/ value objects without resorting to 3rd party libraries like Lombok.
But for the starters, let me give a quick introduction of Java records :
- Java records are special class types and they are primarily meant to be data holders similar to our old POJOs or the Lombok annotated classes.
- The records help us to write lean code for the POJOs by generating the getters/equals/hashcode/toString methods.
- Sure we all have been using Lombok all the while exactly for the same purpose but records are a core JDK feature now and hence better to use them. Less dependency and hence leaner.
- However there are some differences between the Lombok annotated classes and records:
- Unlike Lombok, there are no setters for the fields. So you can’t change the field values after object creation. This is a big difference with Lombok !
- Unlike lombok, there are not getter methods but rather methods close to the fieldnames. So if there is a field named age, the method name will be age()
- Unlike lombok, there are no out of the box builders provided. Only way to create objects is to use the constructor. I came across this Github repo (https://github.com/Randgalt/record-builder) using which we can also add builder class and methods in java. Kudos to the developer(s), I think this was a welcome addition to the community as many of us were using builders during object creation. I also experimented with their code and below is a sample code which works perfectly fine !
- Now conceptually there are few other important points about records which are worth remembering:
- Records are final classes and hence they can’t be extended
- Since fields in records are immutable, there are no setters.
- We can’t create a record by extending another class as records already implicitly inherit java.lang.Record
- We can indeed write functions inside of record types but in my opinion that is not the best use of records. Records are a semantic feature meant to be data carriers without any behaviour.
Now let us see below how easily a record type can be declared in Java in a single line and this in turn generates (during compilation) the constructor, getters and equals, toString and hashcode methods (note the curly braces at the end which could have been left out I think):
public record EmployeeRecord(int id, String name) {}
So now we understand and have seen what records are , let us understand the main use cases of records:
- Value objects or Data Transfer Objects : Records are primarily meant to be data carriers and this is probably the best use where we were using Lombok. So think of any value objects (request / response objects in REST world and that can be implemented as records)
- Also Spring framework is supporting records as value objects already. So it can be used as request / response objects. I have seen usage of records also as service but I would not recommend that as records are primarily immutable data holders.
- Jackson also has support for records
- Records can’t be used as JPA entities
So that was my take. In a nutshell, records are light-weight data carriers and should be used in place of Lombok at some places. If we want builders, we can use the dependency mentioned earlier but again that would mean another extra dependency and then why not use Lombok (but then records are immutable which is an advantage) !! So I hope probably builders would be added to the records as a feature in one of the future JDK releases. Also records are not meant to be used where there is business logic like our service classes or business objects though we can use them technically because we can write methods.