Pattern Matching for instanceof

Quick summary:

  • Simplifies type checking and casting with instanceof, reducing boilerplate and improving readability.
  • Released in Java 16 (2021), but introduced in Java 14 (2020).

Key Features

  • Eliminates Redundant Casting: Automatically casts the variable to the target type if instanceof check is true.
  • Enhanced Readability: Makes code easier to read and maintain by reducing boilerplate around type checking.
  • Safe and Concise: Ensures type safety and reduces the possibility of ClassCastException, allowing for more concise and error-free code.

Example

Before Java 17:

Before, you had manually cast an object after asserting it was possible with an instanceof operation.

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

After Java 17:

With the new pattern matching, the use of instanceof immediately automatically casts the object to that type.

if (obj instanceof String s) {
    System.out.println(s.length());
}

👩‍💻 Hands-on Demo: Pattern Matching for instanceof

  1. Write an abstract Pet-class and implementing Cat-, Dog– and Hamster-classes, according to the UML-diagram.
  2. In the main-method of a PetsApp-class, make a list of pets.
  3. Loop through each pet, have each one make a sound, feed each one, and if it’s a cat let it purr, and if it’s a dog let is wag its tail.
    • Use pattern matching for instanceof to achieve this without casting.

Solutions

🕵️‍♂️ Click here to reveal the solutions
public class PetsApp {
    public static void main(String[] args) {
        Pet[] pets = new Pet[]{new Cat("Picasso"), new Dog("Gimli"), new Hamster("Archimedes"),};

        for (Pet pet : pets) {
            pet.makeSound();
            pet.feed();
            if (pet instanceof Cat c) {
                c.purr();
            } else if (pet instanceof Dog d) {
                d.wagTail();
            }
        }
    }
}
public abstract class Pet {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void makeSound();

    public abstract void feed();
}
public class Cat extends Pet {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }

    @Override
    public void feed() {
        System.out.printf("Feeding %s with a catnip-based diet...\n", getName());
    }

    public void purr() {
        System.out.printf("%s is purring...\n", getName());
    }
}
public class Hamster extends Pet {
    public Hamster(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println("Ssssssssssssssssss!");
    }

    @Override
    public void feed() {
        System.out.printf("Feeding %s with a hamster food diet...\n", getName());
    }
}

Summary

  • Automatic and Safe Casting: This feature minimizes coding errors and eliminates redundant casting by automatically casting objects if the instanceof check is true.
  • Cleaner Code: The new feature reduces boilerplate, improving code readability and maintainability.