Working with Pattern Matching

1. Using Pattern Matching for instanceof

Example: Auto-cast pattern

if (obj instanceof String s && !s.isEmpty()) {
    System.out.println(s.toUpperCase());
}
AspectDetail
Variable scopeTrue branch + remainder of && expression
Negation!(obj instanceof String s) — s usable AFTER if

2. Understanding Type Patterns

PatternForm
TypeType identifier
Varvar x (matches anything)
ConstantLiteral in switch case
Nullcase null

3. Using Pattern Matching in switch

Example: Switch with patterns

String format(Object o) {
    return switch (o) {
        case Integer i -> "int " + i;
        case Long l    -> "long " + l;
        case String s  -> "string \"" + s + "\"";
        case null      -> "null";
        default        -> o.toString();
    };
}
RuleDetail
Selector typeAny reference type
DominanceMore specific patterns must come first
Null handlingExplicit case null required (else NPE)

4. Using Guarded Patterns

Example: when clause

switch (shape) {
    case Triangle t when t.equilateral() -> "equilateral";
    case Triangle t -> "general triangle";
    default -> "other";
}
ElementDetail
when clauseBoolean guard added to pattern
Order mattersGuarded version before plain

5. Understanding Record Patterns JAVA 21+

Example: Record pattern

record Point(int x, int y) {}
if (obj instanceof Point(int x, int y)) {
    System.out.println(x + ", " + y);
}
FormResult
Point(int x, int y)Bind components by name
Point(var x, var y)Use type inference

6. Deconstructing Records with Patterns

MechanismDetail
Auto-extractComponents bound to local vars
Type checkCombined with instanceof or switch
No accessors neededDirect component access

7. Using Nested Record Patterns

Example: Nested deconstruction

record Line(Point start, Point end) {}
if (line instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
    double dist = Math.hypot(x2 - x1, y2 - y1);
}
CapabilityDetail
Arbitrary nestingDeconstruct nested record components
Mix with varReduces verbosity

8. Understanding Pattern Matching Exhaustiveness

SelectorExhaustive Requirement
Sealed typeAll permitted subtypes covered
EnumAll constants covered
Record patternsAll component combinations covered
Otherdefault required

9. Combining Patterns with Sealed Classes

BenefitDetail
Type-safe enumsReplace tagged unions
Compile-time checksAdding subtype reveals all switches needing update
Cleaner ADTsAlgebraic data types in idiomatic Java

10. Using Unnamed Patterns JAVA 21 PREVIEW

Example: Underscore for unused

// Preview: unnamed pattern variable
if (obj instanceof Point(int x, _)) { ... }
switch (r) {
    case Success(_) -> handleOk();
    case Failure(var err) -> log(err);
}
SymbolUse
_Discard component (unused binding)
StatusPreview as of Java 21; standardized in later releases