Java Records :

RMAG news

All About Java Records :

Overview :
Java Records, introduced in Java 14 as a preview feature and finalized in Java 16, provides a concise way to model immutable data. They simplify the boilerplate code needed for data-carrying classes by automatically generating methods like equals(), hashCode() and toString()

By the end of this post you will understand:

What records are in Java?
How to create and use records in Java?
The benefits of using records in Java?
And some limitations of records in Java?

What are Records?
A record in Java is a special kind of class that is designed to hold immutable data. It automatically provides implementations for methods like:

equals()
hashCode()
toString()
Getters for all fields

Why Use Records?
Records help reduce boilerplate code in data classes. Instead of writing constructors, getters, equals(), hashCode(), and toString() methods manually, we can define all of this with a single line of code

How to Define a Record :
Here’s how we can define a simple record:

public record Point(int x, int y) {
}

This single line of code automatically provides:

A constructor
Getters (x() and y())
equals(), hashCode(), and toString() methods

Example: How to use Records
Let’s see how we can use the Point record:

public class Main {
public static void main(String[] args) {
Point point = new Point(3, 4);

// Using the auto-generated toString() method
System.out.println(point); // Output: Point[x=3, y=4]

// Accessing the fields using auto-generated methods
System.out.println(“X: ” + point.x()); // Output: X: 3
System.out.println(“Y: ” + point.y()); // Output: Y: 4
}
}

Example: Custom Methods in Records :
You can also add custom methods to records:

public record Point(int x, int y) {
public double distanceFromOrigin() {
return Math.sqrt(x * x + y * y);
}
}

public class Main {
public static void main(String[] args) {
Point point = new Point(3, 4);
System.out.println(“Distance from origin: ” + point.distanceFromOrigin()); // Output: 5.0
}
}

Custom Constructors :
We can also define custom constructors in records, but they must delegate to the canonical constructor:

public record Point(int x, int y) {
public Point(int x) {
this(x, 0); // Delegating to the canonical constructor
}
}

Limitations of Records :

Immutability: Records are immutable by design. You cannot change the values of their fields after creation.

No Inheritance: Records cannot extend other classes. They implicitly extend java.lang.Record

All-Args Constructor: We cannot create a no-argument constructor directly in records. We must always provide all the components.

When to Use Records :
Use records when:

We need a simple, immutable data carrier class

We want to reduce boilerplate code for equals(), hashCode(), and toString() methods

We don’t need to extend another class or implement complex behavior

Practical Example :
Let’s create a more complex example with a Person record:

public record Person(String name, int age) {
public Person {
// Custom constructor with validation
if (age < 0) {
throw new IllegalArgumentException(“Age cannot be negative”);
}
}

// Custom method
public String greeting() {
return “Hello, my name is ” + name + ” and I am ” + age + ” years old.”;
}
}

public class Main {
public static void main(String[] args) {
Person person = new Person(“Alice”, 30);
System.out.println(person.greeting()); // Output: Hello, my name is Alice and I am 30 years old.
System.out.println(person); // Output: Person[name=Alice, age=30]
}
}

Key Points :

Definition:
public record Person(String name, int age) {}

Custom Constructor:
Validates that age is non-negative

Custom Method:
Adds a greeting() method

Conclusion :
Java Records provide a simple and powerful way to create immutable data classes with minimal boilerplate code. They are especially useful for modeling data transfer objects and other simple data carriers. By understanding and using records, you can write cleaner and more concise code.