Java Pattern Matching
In this page:
if (object instanceof Type variable) {
// use variable
}
switch (object) {
case Type variable -> expression;
default -> expression;
}
Pattern Matching with instanceof
Pattern matching for instanceof simplifies the classic type-check-then-cast pattern by combining both steps into a single expression. Instead of checking instanceof and then separately casting on the next line, the matched, correctly-typed variable is bound automatically as part of the check itself.
Example: Pattern Matching with instanceof
public class Main {
public static void main(String[] args) {
Object obj = "hello";
if (obj instanceof String s) { // bound and cast in one step
System.out.println(s.toUpperCase());
}
}
}
Login to try C/C++/Java/PHP code in the editor
Pattern Variable Scope
A pattern variable introduced by pattern matching is only considered in scope in the branches of code where the type check is statically guaranteed to have succeeded. This prevents you from accidentally referencing an unset or wrongly-typed variable outside that guaranteed region.
Example: Pattern Variable Scope
public class Main {
public static void main(String[] args) {
Object obj = "text";
if (obj instanceof String s && s.length() > 2) {
System.out.println(s); // s is only in scope where the check succeeded
}
}
}
Login to try C/C++/Java/PHP code in the editor
Pattern Matching in Switch
Pattern matching can also be used inside switch statements and switch expressions, letting a single switch match a variable against several different classes and automatically cast it to the matched type inside each corresponding case.
Example: Pattern Matching in Switch
// Define the class Main
public class Main {
static String describe(Object obj) {
// Send switch (obj) { back to the caller
return switch (obj) {
case Integer i -> "Integer: " + i;
case String s -> "String: " + s;
default -> "Unknown";
};
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Print a line to the console
System.out.println(describe(42));
}
}
Login to try C/C++/Java/PHP code in the editor
Switch Patterns with Guards
You can attach conditional checks, called guards, to individual switch cases using the when keyword. This lets you filter within a single pattern-matched case, for example matching a specific class but only when one of its fields also satisfies an extra condition.
Example: Switch Patterns with Guards
// Define the class Main
public class Main {
static String classify(Object obj) {
// Send switch (obj) { back to the caller
return switch (obj) {
case Integer i when i > 100 -> "Big integer";
case Integer i -> "Small integer";
default -> "Not an integer";
};
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Print a line to the console
System.out.println(classify(500));
}
}
Login to try C/C++/Java/PHP code in the editor
Record Patterns
Record patterns let you deconstruct a record object directly as part of a type check, immediately exposing its individual component fields as local variables. This avoids the extra step of matching the record's type and then separately calling its accessor methods.
Example: Record Patterns
public class Main {
record Point(int x, int y) {}
public static void main(String[] args) {
Object obj = new Point(3, 4);
if (obj instanceof Point(int x, int y)) { // deconstructed directly
System.out.println(x + "," + y);
}
}
}
Login to try C/C++/Java/PHP code in the editor
- Using the pattern variable outside the branch where the match is known to succeed, such as after
if (!(obj instanceof String s)), which gives a 'cannot find symbol' error. - Putting a general case like
case Object obefore a specific one likecase String s, which is a compile error because the later case is dominated. - Passing
nullto a patternswitchwithout acase null, which throws aNullPointerException.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: