8 Pattern Matching
Pattern matching involves testing whether an object has a particular structure, then extracting data from that object if there's a match. You can already do this with Java. However, pattern matching introduces new language enhancements that enable you to conditionally extract data from objects with code that's more concise and robust.
A pattern describes a test that can be performed on a value. Patterns appear as operands of statements and expressions, which provide the values to be tested. For example, consider this expression:
s instanceof Rectangle r
The pattern Rectangle r
is an operand of the
instanceof
expression. It's testing if the argument
s
has the type given in the pattern, which is
Rectangle
. Sometimes, the argument that a pattern tests is called
the target.
Note:
When the operand to the right ofinstanceof
is a pattern, like the previous example, then
instanceof
is the pattern match operator.
When the operand to the right of instanceof
is a type, then
instanceof
is the type comparison operator. The
following example uses instanceof
as the type comparison
operator:
s instanceof Rectangle
A pattern can declare zero or more pattern variables. For example,
the pattern Rectangle r
declares only one, r
.
The process of testing a value against a pattern is called pattern
matching. If a value successfully matches a pattern, then the pattern variables
are initialized with data from the target. In this example, if s
is a
Rectangle
, then s
is converted to a
Rectangle
and then assigned to r
.
Patterns can also appear in the case
labels of a switch
statement or expression. For example:
public static double getArea(Shape s) throws IllegalArgumentException {
switch (s) {
case Rectangle r:
return r.length() * r.width();
case Circle c:
return c.radius() * c.radius() * Math.PI;
default:
throw new IllegalArgumentException("Unrecognized shape");
}
}
A type pattern consists of a type along with a single pattern
variable. In this example, Rectangle r
is a type pattern.
A record pattern consists of a record type and a (possibly empty) record pattern list. For example, consider this record declaration and expression:
record Point(double x, double y) {}
// ...
obj instanceof Point(double a, double b)
The record pattern Point(double x, double y)
tests whether the target
obj
is a Point(double, double)
. If so, it extracts
the x
and y
values from obj
directly
and assigns them to the pattern variables a
and b
,
respectively.