JDK prepares to use pattern matching in future versions. In JDK 12 pattern matching has been implemented in switch expression. And the same is being implemented to instanceOf
in JDK 14 as a preview feature.
In java program, instanceof
include logic that combines testing if an expression has a certain type, and then conditionally extracting components of its state for further processing.
if(obj instanceof Person){
int age = ((Person)obj).getAge();
//use age to perform business logic
}
Three things are happening here:
- Type Test (is
obj
anInteger
), - Type Casting (casting
obj
toPerson
) - Destructuring (extracting the
age
component from thePerson
)
Initial two step seems unnecessary where we are doing test and cast. As the only point of type testing is to work with the cast object. To resolve this, pattern matching has been introduced for instanceof
.
A pattern is a combination of a match predicate that determines if the pattern matches a target, along with a set of pattern variables that are conditionally extracted if the pattern matches the target.
In JDK same can be achieved with the below code.
if(obj instanceof Person person){
int age = person.getAge();
//Business logic based on age
}
Here obj
is tested to see if it is an instance of Person
. If so, it is cast to Person
, and the result assigned to person
variable. Also, the variable person is only in the current scope and assigned only when the respective pattern match expressions returns true
. person
variable will not be accessible in any other location.
Using patterns with instanceof
simplifies commonly messy operations, such as the implementation of equals()
methods. For person
class equals method can be implemented as below.
@Override
public boolean equals(Object o) {
if (this == o) return true;
return (o == null || (o instanceof Person person && person.getAge() == age));
}
instanceof pattern matching Example
import java.util.Objects;
public class InstanceOfPatternMatching {
public static void main(String[] args) {
Object obj = new Person(9);
Person person = new Person(19);
if (obj.equals(person)) {
System.out.println("Objects are same");
} else {
System.out.println("Objects are diff");
}
// Pre JDK 14
if (obj instanceof Person) {
int age = ((Person) obj).getAge();
// use age to perform business logic
}
//JDK 14
if (obj instanceof Person person1){ //
int age = person1.getAge();
System.out.println("Age is " + age);
}
//System.out.println(person1.getAge()); person1 is not accessible here
}
}
class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public int hashCode() {
return Objects.hash(age);
}
public int getAge() {
return age;
}
//pre JDK 14
// @Override
// public boolean equals(Object o) {
// if (this == o) return true;
// if (o == null || !(o instanceof Person)) return false;
// Person person = (Person) o;
// return age == person.age;
// }
//JDK 14
@Override
public boolean equals(Object o) {
if (this == o) return true;
return (o == null || (o instanceof Person person && person.getAge() == age));
}
}
Since Java 11, major releases can contain changes that are not available by default, to enable these features a command-line flag –enable-preview is required. Due to which it is called preview language features. Java 12‘s switch expressions were the first such feature.
This change(instanceof pattern matching) is still part of preview in JDK 14. Hence it cannot be directly compiled or run with JDK 14. To compile or run use below commands.
compile
javac --enable-preview --release 14 InstanceOfPatternMatching.java
run
java --enable-preview InstanceOfPatternMatching
Click here to know more about enabling the preview feature in java.