Using “record”

Java 14’s introduction of the record type has been a game-changer since it’s reducing boilerplate code to enhancing data immutability, records are a valuable addition to Java’s toolkit.

The example below demonstrates how record might replce the Lombok library.

class JEP_359_Records {
    public static void main(String...args) {
        System.out.println("Hello World");

        var emp1 = new Employee("John", "Washington");
        var emp2 = new Employee("John", "Washington");

        //emp1.firstName = "Alex"; // ERROR: the properties are implicitly final.
        // emp1.firstName("Alex"); // ERROR: the properties are implicitly final.
    
        System.out.println(emp1); // toString(), output: Employee[firstName=John, lastName=Washington]
        System.out.println(emp1.hashCode()); // hashCode()
        System.out.println(emp2.hashCode()); // hashCode()
        System.out.println(emp1.equals(emp2)); // equals(), output: true

        var emp3 = new Employee(null, null);
        System.out.println(emp3); // custom constructor sets Unknown

        // we can create a custom static method building the class
        var emp4 = Employee.unnamed("Washington");
        System.out.println(emp4);
    }

    public record Employee(String firstName, String lastName) {
        // firstName, lastName are final (immutable)
        // Automatically generated constractor replaces @AllArgsConstructor
        
        // It's not possible for some values to be mutable and some not
        
        // Overriden constructors are not allowed
        // Custom constructor is:
        public Employee {
            if (firstName == null) {
                firstName = "Unknown";
            }
            if (lastName == null) {
                lastName = "Unknown";
            }
        }

        // Custom static method
        public static Employee unnamed(String lastName) {
            return new Employee("Unnamed", lastName);
        }
    }
}

Link to Bitbucket