Sunday 23 May 2021

Java14: Record type

Record type is a preview feature in Java14, provides a compact syntax for classes which are transparent holders for shallowly immutable data.

 

For example, prior to java14, to define an immutable Employee class, you should write following code.

 

Employee.java

public final class Employee {

	private final Integer id;
	private final String firstName;
	private final String lastName;
	private final int age;

	public Employee(Integer id, String firstName, String lastName, int age) {
		super();
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
	}

	public Integer getId() {
		return id;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + "]";
	}

}

With the record type, you can define an immutable Employee class in a compact form like below.

 

EmployeeRecord.java

public record EmployeeRecord(Integer id, String firstName, String lastName, int age) {

}


Record has a name and state description. State description declares the components of the record. In the above example,

a.   Name is EmployeeRecord and

b.   State description is (Integer id, String firstName, String lastName, int age)

 

You can access the properties of EmployeeRecord using method syntax like id(), firstName(), lastName(), age().

 

RecordDemo.java

public class RecordDemo {
	public static void main(String args[]) {
		EmployeeRecord emp1 = new EmployeeRecord(1, "Krishna", "Gurram", 32);
		
		System.out.println("id : " + emp1.id());
		System.out.println("firstName : " + emp1.firstName());
		System.out.println("lastName : " + emp1.lastName());
		System.out.println("age : " + emp1.age());
		System.out.println("emp : " + emp1);
	}

}


Output

id : 1
firstName : Krishna
lastName : Gurram
age : 32
emp : EmployeeRecord[id=1, firstName=Krishna, lastName=Gurram, age=32]


What is happening under the hood when you define a record?

a.   A private final field for each component of the state description;

b.   A public read accessor method for each component of the state description, with the same name and type as the component;

c.    A public constructor, whose signature is the same as the state description, which initializes each field from the corresponding argument;

d.   Implementations of equals and hashCode that say two records are equal if they are of the same type and contain the same state; and

e.   An implementation of toString that includes the string representation of all the record components, with their names.

 

Can I add additional fields to the record?

Yes, you can add an additional field to the record. But the additional field must be static.

 

Can I add methods to the record?

Yes, you can add both instance and static methods to the record. An instance method can access the internal state of the record fields.

 

EmployeeRecord.java

public record EmployeeRecord(Integer id, String firstName, String lastName, int age) {

	private static final String ORG_NAME = "ABC CORP";

	public static String getOrgName(){
		return ORG_NAME;
	}

	public String fullName(){
		return firstName + "," + lastName;
	}
}


RecordDemo.java

public class RecordDemo {
	public static void main(String args[]) {
		EmployeeRecord emp1 = new EmployeeRecord(1, "Krishna", "Gurram", 32);
		
		System.out.println("id : " + emp1.id());
		System.out.println("firstName : " + emp1.firstName());
		System.out.println("lastName : " + emp1.lastName());
		System.out.println("age : " + emp1.age());
		System.out.println("emp : " + emp1);

		System.out.println("\nOrganization name : " + EmployeeRecord.getOrgName());
		System.out.println("Full name : " + emp1.fullName());
	}

}


Output

id : 1
firstName : Krishna
lastName : Gurram
age : 32
emp : EmployeeRecord[id=1, firstName=Krishna, lastName=Gurram, age=32]

Organization name : ABC CORP
Full name : Krishna,Gurram


Can I explicitly define a constructor?

Java provides a special consideration is provided for explicitly declaring the canonical constructor (the one whose signature matches the record's state description). The constructor may be declared without a formal parameter list (in this case, it is assumed identical to the state description).

 

Syntax

public RecordName{}

 

EmployeeRecord.java

public record EmployeeRecord(Integer id, String firstName, String lastName, int age) {

	private static final String ORG_NAME = "ABC CORP";

	public EmployeeRecord{
		if(firstName == null){
			throw new IllegalArgumentException("firstName can't be null");
		}

		if(lastName == null){
			throw new IllegalArgumentException("lastName can't be null");
		}

		if(age <= 18){
			throw new IllegalArgumentException("Age must be > 18");
		}
	}

	public static String getOrgName(){
		return ORG_NAME;
	}

	public String fullName(){
		return firstName + "," + lastName;
	}
}


Can I define toString, hashCode and equals methods?

Yes, you can do. For example, below snippet defines toString() method explicitly.

 

EmployeeRecord.java

public record EmployeeRecord(Integer id, String firstName, String lastName, int age) {

	private static final String ORG_NAME = "ABC CORP";

	public EmployeeRecord{
		if(firstName == null){
			throw new IllegalArgumentException("firstName can't be null");
		}

		if(lastName == null){
			throw new IllegalArgumentException("lastName can't be null");
		}

		if(age <= 18){
			throw new IllegalArgumentException("Age must be > 18");
		}
	}

	public static String getOrgName(){
		return ORG_NAME;
	}

	public String fullName(){
		return firstName + "," + lastName;
	}

	public String toString(){
		StringBuilder builder  = new StringBuilder();
		builder.append("id : " + id).append("\n");
		builder.append("firstName : " + firstName).append("\n");
		builder.append("lastName : " + lastName).append("\n");
		builder.append("age : " + age).append("\n");
		return builder.toString();
	}
}

RecordDemo1.java

public class RecordDemo {
	public static void main(String args[]) {
		EmployeeRecord emp1 = new EmployeeRecord(1, "Krishna", "Gurram", 32);
		
		System.out.println("emp details :\n" + emp1);
	}

}

Output

emp details :
id : 1
firstName : Krishna
lastName : Gurram
age : 32

Reference

https://openjdk.java.net/jeps/359

  

Previous                                                    Next                                                    Home

No comments:

Post a Comment