Java switch pattern matching class


In Java 17, pattern matching for switch statements was introduced as a standard feature. This enhancement allows you to simplify and streamline switch statements by combining pattern matching and switch expressions. It improves code readability and reduces boilerplate code.

Here’s an example that demonstrates the usage of pattern matching for switch statements:

public String getShapeType(Shape shape) {
    return switch (shape) {
        case Circle c -> "Circle with radius " + c.getRadius();
        case Rectangle r -> "Rectangle with width " + r.getWidth() + " and height " + r.getHeight();
        case Square s -> "Square with side length " + s.getSideLength();
        default -> "Unknown shape";
    };
}

In the example, we have a method getShapeType() that takes an object of the Shape class as a parameter. The switch statement uses pattern matching to match the specific subclass of Shape and perform corresponding actions.

The cases in the switch statement use the arrow -> syntax to introduce a pattern. Each pattern consists of the subclass name followed by a variable name (c, r, s) that can be used within the case block to access specific properties of the matched object.

The code inside each case block executes when a match is found. In this example, we return a string representation of the shape type along with some specific details.

The default case handles situations where no match is found.

Pattern matching for switch simplifies switch statements by eliminating the need for explicit type casting or using instanceof checks. It also allows for more concise code and better expressiveness when working with complex class hierarchies.

Note that the pattern matching for switch is part of the ongoing efforts to enhance pattern matching in Java and is subject to further improvements and refinements in future Java versions.

Real time Example:

public class UserProcessor {
    public void processUser(User user) {
        switch (user) {
            case Admin admin -> processAdmin(admin);
            case Customer customer -> processCustomer(customer);
            case Guest -> processGuest();
            default -> throw new IllegalArgumentException("Invalid user");
        }
    }

    private void processAdmin(Admin admin) {
        // Process admin user
        System.out.println("Processing admin user: " + admin.getName());
    }

    private void processCustomer(Customer customer) {
        // Process customer user
        System.out.println("Processing customer user: " + customer.getName());
    }

    private void processGuest() {
        // Process guest user
        System.out.println("Processing guest user");
    }

    public static void main(String[] args) {
        UserProcessor processor = new UserProcessor();

        User user1 = new Admin("John");
        User user2 = new Customer("Alice");
        User user3 = User.Guest;

        processor.processUser(user1);
        processor.processUser(user2);
        processor.processUser(user3);
    }
}

// User class hierarchy
sealed interface User permits Admin, Customer {
    String getName();
}

final class Admin implements User {
    private final String name;

    public Admin(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

final class Customer implements User {
    private final String name;

    public Customer(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

enum User {
    Guest
}

In this example, we have a User class hierarchy consisting of an interface User and two implementations Admin and Customer. We also have a Guest user represented as an enum constant.

The UserProcessor class contains a processUser method that accepts a User object and performs different actions based on the user’s type. With the introduction of pattern matching for switch, we can use patterns to match the user type and process them accordingly.

Inside the switch statement, each case specifies a pattern followed by an arrow (->) and the corresponding code block. For example, case Admin admin -> processAdmin(admin) matches when the user is of type Admin and assigns it to the variable admin. Similarly, case Customer customer -> processCustomer(customer) matches when the user is of type Customer and assigns it to the variable customer. The case Guest -> processGuest() matches when the user is of type Guest.

The default case handles any other user types that are not explicitly matched. In this example, if an invalid user is provided, an IllegalArgumentException is thrown.

By using pattern matching for switch, the code becomes more concise and easier to read. It eliminates the need for explicit type checking and casting, making the code more maintainable and less error-prone.

Note: The code example assumes Java 17 or a later version is being used, as pattern matching for switch was introduced in Java 17.