Java Records
Record is a new way of defining a compact class in Java with some restrictions.
Java Record Class
Am here to introduce you to a new kind of class called the Record class, It is a special type of class, which was introduced as a preview feature in Java 14 and finalised in Java 16.
Well if you are new to Record class never used them before, let me show you how it looks like. Let’s define a record class to store product details which includes id, name and price properties. below is the code snippet for record class definition.
public Record Product(id,name,price){
}The above code demonstrates how to defines a record class.
Now let’s use the record class to create an object and store product details. The code snippet below demonstrates creating an object for Record class.
Product product1 = new Product(101,"IPhone16",700);
Product product2 = new Product(102,"GalaxyS24",800);That’s it .. we are done.. wait a minute you might be thinking .. are we missing some thing here in the Record class. Well you are guess is right record class just looks like a function , no variables/fields declaration, no constructor, no methods. how does it work.
Well that’s the reason why we call the record class as a compact class.
You might be wondering how it works.. lets dig into the details of Record class. Brace yourself.
Following is the syntax of record class :
In the above image if you have observed the syntax of Record class, you got a new term called ComponentType. Yes components are something new, let’s explore the components of record class.
What is a Component ?
Well long story short, The components in a Record (ComponentType type1, ComponentType type2, ...) are the list of fields that define the Record's state.
- Each component has a type and a name, and it automatically generates a private final field, an accessor method, and contributes to the canonical constructor.
- You can think of components as immutable variables that define the structure of the Record.
For Example , in public Record Product(int id, String name, float price) , the component type declarations are :
- int id
- String name
- float price
These declarations define the state of the Record and are used to automatically generate:
- Private final fields (e.g.,
private final String name;andprivate final float price;). - Accessor methods (e.g.,
name()andprice())., These methods are used to read field values. - A canonical constructor that initializes these fields.
equals,hashCode, andtoStringmethods.
Note : A canonical constructor is the primary constructor that is automatically generated by the compiler when a record is declared. This constructor initializes all the fields of the record in the order they are defined.
Why Call Them “Component Type Declarations”?
The term “component type declaration” emphasizes that:
- Each component has a type (e.g.,
String,int, etc.). - Each component has a name (e.g.,
name,age, etc.). - Together, the type and name declare a field that will be part of the Record.
Immutability
Records are immutable objects, that means you cannot change their state once they are created. The fields of the record are final and cannot be reassigned.
Extensibility
Records are powerful and flexible. They allow you to add additional functionality, enforce validation logic, and even model hierarchical data structures using nested records. Let’s explore how Records are extensible :
- Add methods to implement additional functionality
you can add your own methods(custom methods) to provide additional fucntionality.
public Record Product(id,name,price){
public void increasePrice() {
this.price *= 1.10f;
}
}public class TestProduct{
public static void main(String[] args){
Product product1 = new Product(101,"IPhone16",700);
product1.increasePrice();
}
}2. Add validation logic in the canonical constructor
Get Mahesh Patluri’s stories in your inbox
Join Medium for free to get updates from this writer.
You can add validation logic to the canonical constructor (the constructor automatically generated for the Record’s fields) to enforce constraints on the data.
public Record Product(id,name,price){
//compact constructor with validation code
Product{
if(price < 0){
throw new IllegalArgumentException("Price cannot be negative");
}
if(name == null || name.isBlank()){
throw new IllegalArgumentException("Name cannot be null or blank");
}
}
//custom method to increase price by 10 percent
public void increasePrice() {
this.price *= 1.10f;
}
}
3. Use Nested Records for Hierarchical Data Structures
Records can be nested to model hierarchical or complex data structures.
public Record Supplier(id, name){}
public Record Product(id,name,price,Supplier supplier){ }
public class TestItem{
public static void main(String[] args){
Supplier supplier = new Supplier(99901,"Apple");
Product product = new Product(101,"IPhone16",700,supplier);
}
}4. Purpose of Records
The primary purpose of records is to represent simple, immutable data structures where the focus is on the data itself, not on the behaviour or functionality. They are ideal for:
- Data transfer objects (DTOs).
- Value objects (like Point, Rectangle, etc.).
what else we can do with records ?
Records behave like regular classes:
- You can declare them inside a class; nested records are implicitly static
- You can create generic records
- Records can implement interfaces
- You instantiate records with the new keyword
- You can declare in a record’s body static methods, static fields, static initializers, constructors, instance methods, and nested types
- You can annotate records and a record’s individual components
Restrictions on Records
The following are restrictions on the use of records:
- Records cannot extend any class
- Records cannot declare instance fields (other than the private final fields that correspond to the components of the record component list); any other declared fields must be static
- Records cannot be abstract; they are implicitly final
I hope, now you have a good understanding of Records, Start using them in your projects. Happy Coding !





