Table of Contents
Overview
Pattern matching is one of the most powerful features introduced in the recent versions of java. It helps us remove the redundant type casting. In this post, I will cover the key aspects of pattern matching with examples.
Let’s get started.
What is pattern matching?
When talking about pattern matching in java, the first word come to mind is “test”. It is a test to see whether an object has a certain structure.
In this pattern matching code
x instance of String s
- x is called a target
instance of String
is called a predicates
is called pattern variable (there could be more than one pattern variable)
Type patterns
If you are old enough to work with java 8, you are probably familiar with the following code:
Object x = "Hello" ; //Old code if (x instanceof String) { String s = (String) x; System.out.println("[OLD] String: " + s.length()); }
Here, on line 5, I need to create a new object called s and cast x to String before assigning to s.
This is needlessly verbose.
In java 17+, you can do this. No more needless casting!
if (x instanceof String s) { System.out.println("[NEW] String: " + s.length()); }
Key Points:
- Combines the
instanceof
check and cast into a single step. - Reduces boilerplate code.
Record Patterns
When working with records, record patterns help you destructure a record to access its inner properties
static class RecordPatternExample { public static void main(String[] args) { record Dog (String name, int age) {} var dog = new Dog("Fido", 3); if (dog instanceof Dog (String name, int age)) { System.out.println(name + " is " + age + " years old"); } } }
Key Points:
- Matches the structure of the record.
- Extracts record components for direct use.
Switch Expression with pattern matching
Using pattern matching syntax can help reduce the verbosity of switch expressions. You don’t have to worry about missing break;
at every case.
static class SwitchExpressionExample { public static void main(String[] args) { record Dog (String name, int age) {} Object x = 1; switch (x) { case Integer i1 -> System.out.println("x is " + i1); case Dog(String name, int age) -> System.out.println(name + " is " + age + " years old"); default -> System.out.println("x is not an integer or a dog"); } } }
Key Points:
- Combines the power of
switch
and pattern matching. - Cleaner and more expressive than traditional
switch
statements.
Sealed Classes and Patterns
Sealed classes restrict inheritance, allowing pattern matching to ensure type safety and exhaustiveness.
static class SealedClassExample { sealed interface Shape permits Circle, Rectangle {} record Circle(double radius) implements Shape {} record Rectangle(double length, double width) implements Shape {} public static void main(String[] args) { Shape shape = new Circle(1.0); switch (shape) { case Circle(double radius) -> System.out.println("Circle with radius " + radius); case Rectangle(double length, double width) -> System.out.println("Rectangle with dimensions " + length + "x" + width); } } }
Key Points:
- Sealed classes define a closed hierarchy.
- Ensures all possible cases are covered.
Conclusion
In this post, I introduced you to the concept of pattern matching in java, the code example is available here
I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.