The instanceof operator in Java 14 has been enhanced to take advantage of Pattern Matching. This new preview feature is simple, easily understood and well implemented but Hold Up! Before using this new feature, a word of caution ..
Pattern Matching for instanceof in Java 14
The instanceof operator in Java 14 has been extended to allow for what’s called a “test type pattern” which allows for Pattern Matching to be used. This test type pattern is a combination of a predicate that specifies a Type (like instanceof Type) and a binding variable (that’s what is new here).
The code below is the usual way we have all known to use the instanceof operator. Notice the boilerplate code on lines 9 and 14 in which we have to perform an explicit cast. We also always have to declare a local variable which in this case is of type HydroElectricity and NuclearElectricity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//Boilerplate, pre Java 14 private void loopThroughProviders(List<ElectricityProvider> electricityProviders) { Electricity electricity; for (ElectricityProvider provider: electricityProviders) { if (provider instanceof HydroElectricity) { HydroElectricity hydroElectricity = (HydroElectricity)provider; electricity = hydroElectricity.generateHydroElectricty(); } else if (provider instanceof NuclearElectricity) { NuclearElectricity nuclearElectricity = (NuclearElectricity)provider; electricity = nuclearElectricity.generateNuclearPower(); } else { throw new RuntimeException("Unknown Type!"); } System.out.println(electricity); } } |
Now, here is how you would re-write the above code using the Java 14 instanceof operator. Notice the new binding variable after the instanceof operator on lines 7 and 12 which is extracted from the target only if the condition (predicate) successfully applies.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Pattern matching in Java 14 for instanceof operator private void loopThroughProvidersJava14(List<ElectricityProvider> electricityProviders) { Electricity electricity; for (ElectricityProvider provider: electricityProviders) { if (provider instanceof HydroElectricity hydroElectricity) { electricity = hydroElectricity.generateHydroElectricty(); } else if (provider instanceof NuclearElectricity nuclearElectricity) { electricity = nuclearElectricity.generateNuclearPower(); } else { throw new RuntimeException("Unknown Type!"); } System.out.println(electricity); } } |
No more explicit casting and no more declaration of local variables, less boilerplate code .. great! Just be aware that there are some scoping rules with the new binding variable that are well described in the JEP 305 .
This new feature also is quite useful when writing your on equality methods and really streamlines 1 liner return statement. Readability of this type of code is improved and less susceptible to runtime errors arising from incorrect casting.
Code available on GitHub here.
Hold Up! | instanceof
Although Java 14’s new instanceof feature is great, we should remember that sometimes using instanceof can be considered a code smell or an anti-pattern. I purposely coded the example above to showcase how NOT to write the code in order to demonstrate this pitfall.
The issue when you design your OWN code like the example above is that it´s not very OO’ish (Object Orientated) and instead is quite procedural. Did you catch that if/else if/else?
What if I added other Types of electricity providers? The if statement would grow in that function and you would probably find your self pasting similar code elsewhere in your project. What if you forgot to add an extra if/else branch in all the right places when a new Type was introduced?
This type of “if this do that, else do that” code is not good for maintainability. We can do better to avoid this type of procedural code by instead taking advantage of good OO design principles. If done early on, we don’t even need instanceof in this example! So if you see yourself jumping on this new feature, think first … is there a better way?
Should I use intanceof ? | Alternatives
There are times when “yes” you have to use it and that is when this new pattern matching feature will be the right tool for the job. Take for example a case where you are using a 3rd party library where you did not write the code or legacy code which you can’t modify … that is acceptable.
For our OWN code, there are other alternatives like Polymorphism which we should of used in the example above. Strive to replace conditionals with polymorphism whenever you catch yourself playing the if/else or switch case game.
You could opt for using a design pattern like the Visitor Pattern. This is a more complex solution, it is not free! It’s a trade off since you have more Classes to write/maintain therefore increasing the complexity of the design. However you get a more OO’ish design and can leverage compile time safety when adding new Types. It´s an option you can weigh.
The alternatives I mentioned are very well documented and my aim is not to showcase them in this post. My focus is rather to shine light on alternatives and cautiously advise you about the pitfalls of using instanceof in your own design.
You can take a look at the Video version of the tutorial on YouTube where I also go through the solution using Polymorphism.
Preview Feature
You can check out the JEP 305 enhancement proposal for reference, just be warned that this is as a preview feature which must be explicitly set in order to be enabled (via –enable-preview).
Preview features are treated as experimental before being made officially part of any future JDK release – developer feedback is welcome here at the Amber mailing list.
Summary
The instanceof pattern matching capabilities which Java 14 has introduced are a welcomed improvement since it reduces boilerplate code and eliminates incorrect explicit casts which can surface as runtime exceptions.
Just stop and think before you use it in your own code. It may lead to a less maintainable design which is a byproduct of the procedural programming style you inherit when using instanceof. As always, being well informed on the pros and cons will guide you in using the right tool for the right job.
The code is available on GitHub here. The alternative solution using Polymorphism is in the GitHub repository 🙂
Check out some more preview feature articles here …