Notice

╠ This is my personal blog and my posts here have nothing to do with my employers or any other association I may have. It is my personal blog for my personal experience, ideas and notes. ╣
Showing posts with label JDK15. Show all posts
Showing posts with label JDK15. Show all posts

Sunday, August 9, 2020

New way to create immutable object in Java ['record'] JEP 384: Records

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. 
package dto;
import java.time.LocalDate;
public record Person(Name name, LocalDate dob, Address address) {
}
view raw Person.java hosted with ❤ by GitHub

A record with multiple constructors and instance method. 
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;
}
}
view raw Address.java hosted with ❤ by GitHub

A record with constructor level validation, static method and override 'equals' method. 
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());
}
}
view raw Name.java hosted with ❤ by GitHub

In this class, we are accessing the field with the internal method and other methods like 'toString', 'equals' and 'hashCode'. 

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());
}
}
}
view raw TestRecord hosted with ❤ by GitHub

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!

Sunday, July 26, 2020

Now Java Developer can write their 'Will' [JDK15 JEP 360: Sealed Class (Preview)]

As a developer if you want to control who can extend your class or interface. 

In this enhancement of Java programming language, new keywords are introduced sealed, non-sealed and permit at the class level. 

A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so. If you try to implement or extend to other class which is not permitted then the code will not compile. For example,
public sealed class Point permits Line


permit keyword defines which are the subclasses or interfaces can be extended or implemented from this class. For example, 
public sealed class Point permits Line
Point class only permits Line class to extend directly. 

A non-sealed class or interface will allow this class to be extended. 
For example,
public non-sealed class Line
Permitted class Line is open for any unknown class extension. 


public sealed class Shape permits Circle {
public void name() {
System.out.println("This is Shape.");
}
public static void main(String args[]) {
Shape shape = new Shape();
shape.name();
Shape newShape = new Circle();
newShape.name();
}
}
non-sealed class Circle extends Shape {
@Override
public void name() {
System.out.println("This is Circle.");
}
}
view raw Shape.java hosted with ❤ by GitHub

To Compile

To Run




A permitted subclass must define whether it could be extended to a specific class (sealed) or open to any unknown class(non-sealed) or not open for any extension (final). 



When a not permitted class extend a sealed class. 





Happy Coding and keep learning!

Saturday, July 18, 2020

JDK 15 [Pattern Matching of instanceof operator ]

This is an enhancement of Java language with pattern matching for the instanceof operator. Currently, this feature is in the second preview in JDK 15.

So currently when we need to cast an object, we check it using instanceof operation then only we cast the object to save our self from class cast exception.

existing instanceof operator

In the above code snippet, we have to explicitly cast it to an object. 
In this enhancement, we no more have to do it. 



To run the below code you need to install JDK 14 or above and have to enable the preview feature of javac & java. 
In order to enable that preview feature. 
javac 
      --enable-preview 
        -release <version> 
      <Source file>

java 
    --enable-preview 
       <Compiled class> 


// Anindya Bandopadhyay (anindyabandopadhyay@gmail.com)
public class PatternMatchingOfInstance {
public static void main(final String args[]) {
PatternMatchingOfInstance instance = new PatternMatchingOfInstance();
Object obj = instance.getValue((instance.new IntValue(1)));
if(obj instanceof Integer) {
final Integer intValue = (Integer) obj;
System.out.println(String.format("Int value = %d", intValue));
}
//JEP 375: Pattern Matching for instanceof (Second Preview)
if(obj instanceof Integer objInt) {
System.out.println(String.format("Using Pattern Matching for instanceof: Int value = %d", objInt));
}
}
private Object getValue(final Value value) {
return value.getValue();
}
interface Value {
Object getValue();
}
class IntValue implements Value {
private final int value;
public IntValue(final int value) {
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
}
class BoolValue implements Value {
private final boolean value;
public BoolValue(final boolean value) {
this.value = value;
}
@Override
public Boolean getValue() {
return value;
}
}
class StrValue implements Value {
private final String value;
public StrValue(final String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
}
class DoubleValue implements Value {
private final double value;
public DoubleValue(final double value) {
this.value = value;
}
@Override
public Double getValue() {
return value;
}
}
class FloatValue implements Value {
private final float value;
public FloatValue(final float value) {
this.value = value;
}
@Override
public Float getValue() {
return value;
}
}
}

Output

 Happy Coding!