Java Pattern Matching in switch

🚀 Introduction: Why Use Pattern Matching in switch?

Before Java 21, handling different object types in a switch was not possible directly. Instead, developers were forced to:

Use instanceof checks inside if-else statements
Manually cast objects to their actual types
Use complex and verbose logic to handle multiple types

💡 Java 21 introduces Pattern Matching in switch, making code cleaner and safer.

📌 In this article, you’ll learn:
✅ What is Pattern Matching in switch?
✅ How to simplify type-based logic using pattern matching
Complete examples demonstrating real-world use cases

🔍 The Problem: How Java Handled Type Checks Before Java 21

Before Java 21, you could not use switch on objects unless they were enum, String, or primitive types. Instead, you had to rely on if-else with instanceof checks.

❌ Traditional Approach Using if-else with instanceof (Before Java 21)

public class BeforePatternMatching {
    public static void process(Object obj) {
        if (obj instanceof String) {
            String s = (String) obj;  // Explicit casting needed
            System.out.println("String: " + s.toUpperCase());
        } else if (obj instanceof Integer) {
            Integer i = (Integer) obj; // Explicit casting needed
            System.out.println("Integer squared: " + (i * i));
        } else if (obj instanceof Double) {
            Double d = (Double) obj; // Explicit casting needed
            System.out.println("Double value: " + (d * 2));
        } else if (obj == null) {
            System.out.println("Null value received");
        } else {
            System.out.println("Unknown type: " + obj);
        }
    }

    public static void main(String[] args) {
        process("hello");
        process(5);
        process(10.5);
        process(null);
    }
}

🔹 Output (Before Java 21 using if-else)

String: HELLO
Integer squared: 25
Double value: 21.0
Null value received

📌 Problems with this approach:
Repetitive explicit casting ((String) obj)
Long and difficult-to-read if-else chains
Error-prone when dealing with multiple types
No direct switch support for Object types

✅ Java 21: Pattern Matching in switch (Cleaner & Safer Approach)

Java 21 eliminates the need for instanceof checks and explicit casting by introducing Pattern Matching in switch.

1️⃣ Pattern Matching in switch (No More instanceof or Casting!)

public class PatternMatchingSwitchExample {
    public static void process(Object obj) {
        switch (obj) {
            case String s -> System.out.println("String: " + s.toUpperCase());
            case Integer i -> System.out.println("Integer squared: " + (i * i));
            case Double d -> System.out.println("Double value: " + (d * 2));
            case null -> System.out.println("Null value received");
            default -> System.out.println("Unknown type: " + obj);
        }
    }

    public static void main(String[] args) {
        process("hello");
        process(5);
        process(10.5);
        process(null);
    }
}

🔹 Output (Java 21 Pattern Matching in switch)

String: HELLO
Integer squared: 25
Double value: 21.0
Null value received

📌 Why is this better?
No need for explicit instanceof checks (if (obj instanceof String))
No need for explicit type casting ((String) obj)
More readable & maintainable code
Handles null safely (case null)

2️⃣ Guarded Pattern Matching in switch (Add Conditions to Cases)

Java 21 allows guarded patterns using when, making conditional logic cleaner and more expressive.

public class GuardedPatternMatching {
    public static void processNumber(Number num) {
        switch (num) {
            case Integer i when i > 0 -> System.out.println("Positive integer: " + i);
            case Integer i when i < 0 -> System.out.println("Negative integer: " + i);
            case Double d when d > 10.0 -> System.out.println("Large double: " + d);
            default -> System.out.println("Other number: " + num);
        }
    }

    public static void main(String[] args) {
        processNumber(5);
        processNumber(-3);
        processNumber(15.5);
        processNumber(2.5);
    }
}

🔹 Output:

Positive integer: 5
Negative integer: -3
Large double: 15.5
Other number: 2.5

📌 Why is this useful?
Avoids nested if-else inside switch
Cleaner handling of different value ranges
More expressive case conditions

3️⃣ Using Pattern Matching in switch for Records

Pattern matching also works with Java Records, making object deconstruction easy.

📌 Define a Record

record Person(String name, int age) {}

📌 Use Pattern Matching in switch

public class RecordPatternMatching {
    public static void processPerson(Object obj) {
        switch (obj) {
            case Person p when p.age() >= 18 -> System.out.println(p.name() + " is an adult.");
            case Person p -> System.out.println(p.name() + " is a minor.");
            default -> System.out.println("Not a person.");
        }
    }

    public static void main(String[] args) {
        processPerson(new Person("Amit", 22));
        processPerson(new Person("Neha", 16));
        processPerson("Random String");
    }
}

🔹 Output:

Amit is an adult.
Neha is a minor.
Not a person.

📌 Why is this useful?
Avoids if (obj instanceof Person) { ... } checks
Directly accesses record fields (p.name(), p.age())
More expressive and structured pattern matching

🔑 Key Takeaways

Java 21’s Pattern Matching in switch makes code cleaner and more readable.
No more manual casting or instanceof checks – Java does it automatically.
Supports when guards for condition-based matching.
Works with records, JSON parsing, and event handling.

By using Pattern Matching in switch, your Java code will be faster, safer, and easier to maintain! 🚀

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare