Skip to content
On this page

Record Class

When using String , Integer and other types, these types are immutable classes. An immutable class has the following characteristics:

  • Use final when defining a class, and subclasses cannot be derived;
  • Use final for each field to ensure that no field can be modified after the instance is created.

Suppose we want to define a Point class with two variables x and y , and it is an immutable class. We can write it like this:

java
public final class Point {
  private final int x;
  private final int y;

  public Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public int x() {
    return this.x;
  }

  public int y() {
    return this.y;
  }
}

In order to ensure comparison of immutable classes, equals() and hashCode() methods also need to be overridden correctly so that they can be used normally in collection classes.

We will explain in detail the correct overwriting of equals() and hashCode() later. The purpose of demonstrating the writing of Point immutable class here is that these codes are very simple to write, but very cumbersome.

record

Starting with Java 14, the new Record class was introduced. When we define the Record class, we use the keyword record . Rewrite the above Point class into the Record class, the code is as follows:

java
public class Main {
    public static void main(String[] args) {
        Point p = new Point(123, 456);
        System.out.println(p.x());
        System.out.println(p.y());
        System.out.println(p);
    }
}

record Point(int x, int y) {}

Look carefully at the definition of Point :

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

Rewrite the above definition as class, which is equivalent to the following code:

java
final class Point extends Record {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int x() {
        return this.x;
    }

    public int y() {
        return this.y;
    }

    public String toString() {
        return String.format("Point[x=%s, y=%s]", x, y);
    }

    public boolean equals(Object o) {
        ...
    }
    public int hashCode() {
        ...
    }
}

In addition to modifying the class and each field with final , the compiler also automatically creates a constructor for us, a method with the same name as the field name, and overrides toString() , equals() , and hashCode() methods.

In other words, using the record keyword, you can write an immutable class in one line.

Similar to enum , we cannot directly derive from Record ourselves, and can only be inherited by the compiler through the record keyword.

Constructor

By default, the compiler automatically creates a constructor in the order of variables declared in record and assigns values to the fields within the method. So the question is, what should we do if we want to check parameters?

Assuming that x and y of Point class do not allow negative numbers, we have to add checking logic to the Point construction method:

java
public record Point(int x, int y) {
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException();
        }
    }
}

Notice that the method public Point {...} is called Compact Constructor. Its purpose is to let us write checking logic. The constructor finally generated by the compiler is as follows:

java
public final class Point extends Record {
    public Point(int x, int y) {
        // This is the Compact Constructor we wrote:
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException();
        }
        // This is the assignment code that the compiler continues to generate:
        this.x = x;
        this.y = y;
    }
    ...
}

Point as record can still add static methods. A commonly used static method is of() method, used to create Point :

java
public record Point(int x, int y) {
    public static Point of() {
        return new Point(0, 0);
    }
    public static Point of(int x, int y) {
        return new Point(x, y);
    }
}

This way we can write more concise code:

java
var z = Point.of();
var p = Point.of(123, 456);

Summary

Starting from Java 14, the new record keyword is provided, which makes it very convenient to define Data Class:

  • What is defined using record is an immutable class;
  • Compact Constructor can be written to verify parameters;
  • Static methods can be defined.
Record Class has loaded