As a Java developer, we use POJO every day in our coding. We have to write or generate codes of accessor methods and other methods like 'equals', 'toString' and 'hashCode' or use a library like Lombok.
To make it more simplified Java introducing 'record'. Using which developer need not have to generate or write these code.
Some of the features of these 'record' class.
- implicitly they are final so it cannot be extended or abstracted but can implement an interface.
- java.lang.Record is the superclass of record
- A record cannot define the native method.
- A record field(s) is/are implicitly final
Let's see with an example.
A simple record with no boilerplate code. It provides field accessor method, 'toString', 'equals' and 'hashCode' readily available.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dto; | |
import java.time.LocalDate; | |
public record Person(Name name, LocalDate dob, Address address) { | |
} |
A record with multiple constructors and instance method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dto; | |
public record Address(String line1, String line2,String country,String zipcode) { | |
public Address(String line1, String line2, String zipcode) { | |
this(line1, line2, "India", zipcode); | |
} | |
// Instance Method | |
public String fullAddress() { | |
return line1 + " " + line2 + " " + country + " " + zipcode; | |
} | |
} |
A record with constructor level validation, static method and override 'equals' method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dto; | |
public record Name(Title title, String fname, String lname) { | |
public enum Title { Mr, Mrs, Miss, Master, Dr, Prof} | |
public Name { | |
if(fname == null || lname == null) { | |
throw new IllegalArgumentException("First name and / or Last name cannot be null"); | |
} | |
} | |
// static method | |
public static String fullNameToUpper(Name name) { | |
return (name.title() + " " + name.fname() + " " + name.lname()).toUpperCase(); | |
} | |
// Custom equals method. Not considering title here | |
// Do remember that hashCode method also need to be changed | |
// As this is just an example. Not overriding hashCode method | |
@Override | |
public boolean equals(Object obj) { | |
if(obj == this) { | |
return true; | |
} | |
return obj instanceof Name name && name.fname().equals(fname()) && name.lname().equals(lname()); | |
} | |
} |
In this class, we are accessing the field with the internal method and other methods like 'toString', 'equals' and 'hashCode'.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dto.*; | |
import java.time.*; | |
public class TestRecord { | |
public static void main(String[] args) { | |
String fname = "Andy"; | |
String lname = "Banerjee"; | |
Name name = new Name(Name.Title.Mr, fname, lname); | |
LocalDate dob = LocalDate.of(1990,Month.JANUARY,01); | |
Address addressInIndia = new Address("Networking Street", "Hacker Avenue", "PINcode"); | |
Person person = new Person(name, dob, addressInIndia); | |
System.out.println("Person Name: " + person.name()); | |
System.out.println("Date of Birth: " + person.dob()); | |
System.out.println("Address: " + person.address()); | |
System.out.println("hashCode() = " + person.hashCode()); | |
System.out.println("toString() = " + person.toString()); | |
Person clonePerson = new Person(name, dob, addressInIndia); | |
Address addressOutsideIndia = new Address("Networking Street", "Hacker Avenue", "USA", "ZIPcode"); | |
Person anotherPerson = new Person(name, dob, addressOutsideIndia); | |
System.out.println("====================================="); | |
System.out.println("\n Person object A : " + person); | |
System.out.println("\n Person Object B : " + clonePerson); | |
System.out.println("\n Person Object C : " + anotherPerson); | |
System.out.println("====================================="); | |
System.out.println("Person A & B. Both are equals? => " + person.equals(clonePerson)); | |
System.out.println("Person A & C. Both are equals ? => " + person.equals(anotherPerson)); | |
Name nameWithDrTitle = new Name(Name.Title.Dr, fname, lname); | |
System.out.println("How custom equals working ? Ignoring the title here => " + name.equals(nameWithDrTitle)); | |
System.out.println("Invoking the static method => " + Name.fullNameToUpper(nameWithDrTitle)); | |
System.out.println("Invoking the instance method => " + addressOutsideIndia.fullAddress()); | |
try { | |
Name recordWithValidationCheck = new Name(Name.Title.Mr, null, null); | |
} catch (IllegalArgumentException e) { | |
System.out.println("Added validation. \t::::::: \t" + e.getMessage()); | |
} | |
} | |
} |
Output
To compile these codes
javac --enable-preview --release 15 TestRecord.java
To Run these codes
java --enable-preview TestRecord
Happy coding and keep learning!