Appearance
Lesson 08 · Pattern Matching
Objectives
After this lesson you will be able to:
- Use
instanceofpatterns with binding variables and scope. - Use type patterns in
switch, withnulland guarded (when) labels. - Deconstruct records with record patterns, including nesting.
instanceof patterns
A type pattern tests and binds in one step — no separate cast:
java
Object o = "hello";
if (o instanceof String s && s.length() > 3) {
System.out.println(s.toUpperCase()); // s is in scope and definitely a String
}The binding s is in scope only where the pattern definitely matched — this is flow scoping. After if (!(o instanceof String s)) return;, s is in scope below because control only continues when the match held.
Type patterns in switch
A switch can match on type, replacing long if/else instanceof chains:
java
String describe(Object o) {
return switch (o) {
case null -> "null";
case Integer i -> "int " + i;
case String s -> "str " + s.length();
default -> "other";
};
}Exam trap
A pattern switch handles null only if you add a case null (otherwise a null selector throws NPE). Pattern labels must be ordered so a more specific type comes before a supertype — an unreachable label (dominated by an earlier one) is a compile error.
Guarded patterns (when)
Add a boolean guard with when to refine a case:
java
String size(Object o) {
return switch (o) {
case String s when s.length() > 10 -> "long string";
case String s -> "short string";
default -> "not a string";
};
}Record patterns (deconstruction)
A record pattern matches a record and binds its components directly — and nests:
java
record Point(int x, int y) { }
record Line(Point from, Point to) { }
String f(Object o) {
return switch (o) {
case Line(Point(var x1, var y1), Point(var x2, var y2)) ->
"from (" + x1 + "," + y1 + ") to (" + x2 + "," + y2 + ")";
case Point(var x, var y) -> "point " + x + "," + y;
default -> "?";
};
}SDET note
Pattern matching plus sealed types (Lesson 06) gives exhaustive, branch-complete handling the compiler verifies. For parsing/validation logic this removes a whole class of "forgot a case" bugs — exactly the kind of subtle gap to check in AI-generated switch code.
Key Takeaways
- An
instanceoftype pattern tests and binds at once; the binding follows flow scoping (in scope only where the match is guaranteed). - A pattern
switchmatches by type; addcase nullto handle null, and order specific types before their supertypes (dominated labels won't compile). whenadds a boolean guard to a case label.- Record patterns deconstruct components (and nest), binding fields directly.
Lesson Quiz
In if (o instanceof String s) { ... }, where is s usable?
A pattern switch with no case null receives a null selector. What happens?
Why does this NOT compile?
switch (o) { case Object obj -> "obj"; case String s -> "str"; }What does the record pattern case Point(var x, var y) do?
What does when add to a case label?
Next: Module 03 Mini-Exam. Run the matching code in labs/src/main/java/com/jse21/m03_oop/.