Records in Java

Records in Java

Records were first introduced in Java 14.

What is Java Records?

Records in Java are a concise way to define immutable classes. They focus on data storage and offer:

  • Automatic boilerplate code: The compiler generates getters, equals, hashCode, and toString methods for you.

  • Immutability by default: Record fields are final, promoting thread safety and simplifying reasoning about your data.

public record Person(String name, int age) {
    // No need to explicitly declare constructors, 
    //getters, toString, hashCode, or equals.
}

From this one line of code, the compiler generates the following:

  • final fields with a String name and int age

  • A constructor which sets both the fields with the value (canonical constructor)

  • the accessor methods name() and age()

  • an equals() method that evaluates if two instances are the same if name and age values are the same for both instances

  • a hashcode() method returns the same hashcode for two same instances

  • a toString() method

We can use the record Person defined above as we use a normal Java class.

        Person p = new Person("Ram",12);// using Canonical Constructor
        System.out.println(p);//using ToString
        System.out.println(p.name());// using getter
        System.out.println(p.hashCode()); //using hashCode()
        Person p2 = new Person("Ram", 12);
        System.out.println(p.equals(p2));//using equals()

Static fields in Records

Records can be extended by static (final or non-final) fields. For Example:

public record Person(String name, int age) {
    public static final int DEFAULT_AGE = 0;
    public static String DEFAULT_NAME = "RAJ";
}

Canonical Constructor Overriding

public record Person(String name, int age) {
    public Person(String name, int age) {
        System.out.println("Accessing the Canonical Constructor");
        this.name = name;
        this.age = age;
    }
}

Compact Constructor

There is another concise way of overriding the canonical constructor which is called compact constructor.

public record Person(String name, int age) {
    public Person {
        System.out.println("Accessing the Compact Constructor");
    }
}

Methods in Records

we can also define the static and non-static methods.

public record Person(String name, int age) {
    public void hello(){
        System.out.println("hello");
    }
    public static void bye(){
        System.out.println("Bye");
    }
}

Inheritance in Records

Records can implement interfaces but cannot extend classes and since Records are implicitly final they cannot inherit from them also.

public interface Base {
  int age();
}
public record Person(String name, int age) implements Base {
}

When to use Records?

DTOS, Immutable Objects,API response

\>> Records are a better choice than classes in situations where you are primarily storing data and not defining any behaviour.