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); } } }