Pattern matching in Java 19
Pattern matching got quite an update in Java 19 (although it does require turning on experimental features).
We could already match on instances of subclasses in Java 17:
public static String foo(Object bar) {
return switch(bar) {
case Integer i -> "I'm an Integer: " + i;
case Long l -> "I'm a Long: " + l;
default -> "I'm an object";
};
}
In this example we pattern match over the variable bar
which checks the type and assigns it to either the Integer i
or the Long l
.
Now we can use i
and l
as though they were Integers and Longs respectively.
In Java 19 we can take this a step further with something we call deconstruction.
record Point(int x, int y) { }
var p = new Point(1, 1);
var result = switch (p) {
case Point(var xVal, var yVal) -> "a) x: " + xVal + " y: " + yVal;
};
So, what do we see here?
First we create a record called Point
, then we create an instance of it, and finally we apply pattern matching on it.
But here we see something different.
We now match on case Point(var xVal, var yVal)
.
First it is an instanceof check (whether or not it is an instance of Point), and if so it deconstructs Point into its underlying variables.
It deconstructs the parameters based on their position, so we were free to call them xVal
and yVal
.
Now we are free to use these as variables within this case
statement.
While this is some really nice syntactic sugar, it becomes quite powerful when we include the new when
statement.
With the when
statement we can add boolean expressions to the case
statement, as we can see in the next example:
record Point(int x, int y) { }
var p = new Point(1, 1);
var result = switch (p) {
case Point(var x,var y) when x > 10 -> "a) x is > 10";
case Point(var x,var y) -> "b) x is <= 10";
};
Here we deconstruct Point into its member variables and then match only if x > 10
.
We do need either a default
branch or case Point(var x,var y)
to make the switch statement exhaustive.
Because case Point(var x,var y)
handles all other Point`s it is the same as a `default
in this case as long as we switch over an instance of Point
.
If we combine everything we learned we can now do things like this in the new Java switch
statement:
Object o = 1L;
var result = switch (o) {
case Point(var x,var y) when x > 10 -> "I'm a point with x > 10";
case Point(var x,var y) -> "I'm any other point";
case Long l -> "I'm a Long: " + l;
default -> "I'm something else";
};
So I think we can conclude Java got access to some powerful new tools and personally I am looking forward to using them.