instanceof (Pattern Matching) JEP 305

Ashish Garg
4 min readJan 26, 2020

--

Photo by Bruno Wolff on Unsplash

Every java developer have written code like below

if(str instanceof String ){
int len = ((String)str).length();
}

In above snippet

  • First a test is happening to confirm ‘str’ is of type String class, if yes
  • ‘str’ is getting cast into a String object, after successful casting
  • length is getting calculated and assigned to a int.

you must have asked this question why I have to do this casting if I already checked the type before, after successful type check only control will transfer inside if block then ‘str’ can only be String or its subclass there is no other possibility compiler should not asked me to this unnecessary casting.

And there is always a possibility of writing buggy code like this:

if(str instanceof String ){
int len = ((Integer)str);
}

this will compile just fine by your IDE, and you will be seeing a nice “java.lang.ClassCastException” at runtime.

JEP 305 (Preview in JDK 14)

The instanceof has been extended to support type test pattern. Now you will be coding like this:

if(str instanceof String s){
System.out.println("length is "+s.length());
}

here instanceof is checking type of ‘str’ as String and assigned it to a binding variable ‘s’. This looks much neat in comparison to older version

Few things to keep in mind:

  • Scope of binding variable

One thing to keep in mind that scope of binding variable is only lies in true statement i.e. in below code block

if(str instanceof String s){
}else{
System.out.println(s.length());
}

trying to access binding variable ‘s’ in else block will be compile time error “cannot find symbol” as its not visible there.

Similarly if you have written a code snippet like below

private static void newInstanceOfNeg(Object str){
if(!(str instanceof String s)){
}else{
System.out.println(s.length());
}
}

‘s’ will be accessible in else block only any attempt to access it in if block will be compile time error.

Important Points

If name of binding variable matched with another variable in scope of method or class, it can be nasty place for bug to hide. So we need to be very careful about naming them

  • Binding variable name in method scope

Observer below snippet, here binding variable named as ‘s’ and method also has another local variable with same name

private static void instanceOfFunWithACaveat(Object obj){
String s = "Ash";
if(obj instanceof String s){
System.out.println("length is "+s.length());
}
}

good part is, this will not compile and you will be seeing a error like “error: variable s is already defined”.

But if you write something like below

private static void instanceOfFunWithACaveat(Object obj){
String s = "Ash";
if(obj instanceof String str){
System.out.println("length is "+s.length());
}
}

here binding variable named as ‘str’ but under true block code is still referring to method variable ‘s’. It will compile and run perfectly without any error but such kind of typo might turned out to be a bug.

  • If binding variable has same name as instance variable

Q- What will happen if binding variable has same name as instance variable and you try to access it in true block, see below snippet:

private static String s = "Ash";
private static void instanceOfFunWithoutElseAndACaveat(Object obj){
if(obj instanceof String s){
System.out.println("length is "+s.length());
}
}

and if you are calling this function with

instanceOfFunWithoutElseAndACaveat("Ashish")

you will be seeing output as ‘6’ not ‘3’. Binding variable will take precedence here.

Q- What will happen if binding variable has same name as instance variable and you try to access it in false block, see below snippet:

private static String s = "Ash";
private static void instanceOfFunWithElseAndACaveat(Object obj){
if(obj instanceof String s){
System.out.println("length is "+s.length());
}else{
System.out.println("s is instance variable here"+ s.length());
}
}

and if you are calling this function with

instanceOfFunWithElseAndACaveat(1);

you will be seeing output as ‘3’ because in else block instance variable ‘s’ is visible.

  • Test pattern with && operator

Usually conditional if block has multiple operator to fulfill certain business need. Let’s take a example where ‘&&’ operator is present along with instanceof test pattern, see below snippet:

private static void instanceOfWithAndOperator(Object obj){
if(obj instanceof String s && s.contains("Ash")){
System.out.println("In true block");
}
}

here you can see in if block after instanceof test pattern there is also a contains check separated by ‘&&’ operator. Right side of ‘&&’ will only be execute if test pattern succeeded.

  • Test pattern with || operator

Similar to above, let’s say we have || operator after instanceof test pattern

private static void instanceOfWithOrOperator(Object obj){
if(obj instanceof String s || s.contains("Ash")){
System.out.println("In true block");
}
}

‘s’ will not be accessible to right side of ‘||’ block neither in if statement nor in block (if there is instance variable with same name ‘s’ that will be accessible to if statement and block)

  • Test pattern with null

Let’s say if you are calling below method with null argument.

private static void newInstanceOf(String str){
if(str instanceof String s){
System.out.println("In true block");
}else{
System.out.println("In false block");
}
}

it will simply print “In false block”, instanceof test pattern will only be executed for non null object.

Compile and Run

As record released as preview feature with JDK 14, you need to enable preview to play around with it. To compile a class follow command like below

javac --enable-preview --release 14 <Path of Java Source File>

it will compile and create class. Now to run it simply use java command with enable preview.

If you want to leverage the JDK 11 feature where a single source file can be directly compile and run with single java command follow below command.

java --enable-preview --source 14 <Path of Java Source File>

--

--

Ashish Garg

Father, amateur photographer, software geek. Love all my hats