CodeGym /Courses /JAVA 25 SELF /Pattern Matching for instanceof

Pattern Matching for instanceof

JAVA 25 SELF
Level 65, Lesson 1
Available

1. The problem with the classic instanceof

Let’s start with a bit of nostalgia. Before Java 16, when you needed to check an object’s type and then use it as that type, you had to write a verbose pattern with an instanceof check and an explicit cast:

Object obj = ...; // some object

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

Boring but common pattern

This pattern appears very often — event handlers, working with heterogeneous collections, business logic with inheritance, etc.

Why it’s inconvenient

  • Code duplication — you have to specify the type twice: in instanceof and in the cast.
  • Risk of error — it’s easy to accidentally cast to the wrong type and get a ClassCastException.
  • “Noisy” code — worsens readability, especially with multiple checks.

2. Pattern Matching for instanceof: new syntax

Java 16 added pattern matching for instanceof. Now you check the type and immediately declare a variable of the desired type, available inside the if branch.

New syntax

if (obj instanceof String s) {
    // s is already a String!
    System.out.println("String length: " + s.length());
}
  • After the type in instanceof, write the new variable name: String s.
  • The variable is available only within the block where the condition is true.
  • No need to write the cast (String) — the compiler guarantees it.

What’s the magic? The compiler checks the type and, if it matches, “unwraps” a variable of the required type. Otherwise, the block simply doesn’t execute.

What it looks like in real code

Object obj = "Hello, Java 16+!";

if (obj instanceof String s) {
    System.out.println("Uppercase: " + s.toUpperCase());
} else {
    System.out.println("Not a string!");
}

3. Safety and readability: why this is great

Eliminates ClassCastException

Object obj = 123;
// String s = (String) obj; // Boom! Exception.

With pattern matching, the variable is created only upon a successful type check — there’s simply no “wrong” cast.

Code gets shorter and clearer
Two lines turn into one. Less “noisy” code — easier to read and maintain.

Example: handling multiple types

public static void printInfo(Object obj) {
    if (obj instanceof String s) {
        System.out.println("String length " + s.length());
    } else if (obj instanceof Integer i) {
        System.out.println("Integer: " + (i + 1));
    } else {
        System.out.println("Unknown type: " + obj);
    }
}

4. Usage examples and nuances

Checking multiple types

Object value = ...;

if (value instanceof String s) {
    System.out.println("It's a string: " + s);
} else if (value instanceof Number n) {
    System.out.println("It's a number: " + n);
} else {
    System.out.println("Something else: " + value);
}

Using with null
If the object is null, instanceof always returns false — no NPE, but the block won’t run.

Object obj = null;

if (obj instanceof String s) {
    // This block will NEVER run if obj == null
    System.out.println("String: " + s);
} else {
    System.out.println("obj is null or not a string");
}

Pattern matching with inheritance

class Animal {}
class Dog extends Animal {
    void bark() { System.out.println("Woof!"); }
}

Animal a = new Dog();

if (a instanceof Dog d) {
    d.bark(); // We can call Dog methods without casting!
}

Reminder: the order of checks matters — go from more specific to more general, otherwise the “narrow” checks may not trigger.

Comparison: old vs. new approach

Old way New way (pattern matching)
if (obj instanceof Cat) {
    Cat c = (Cat) obj;
    c.meow();
}
if (obj instanceof Cat c) {
    c.meow();
}

5. Limitations of pattern matching for instanceof

  • Variable scope. The variable from the pattern is visible only in the branch where the check is true.
if (obj instanceof String s) {
    System.out.println(s); // s is accessible
}
// System.out.println(s); // Error! s is not visible here
  • You can’t declare multiple variables of different types in a single condition.
// Compilation error:
if (obj instanceof String s || obj instanceof Integer i) {
    // ...
}
  • Requires Java 16+. On older JDK versions, the new syntax is not supported.

6. Practical examples (based on a simple app)

Let’s imagine a simple Task Manager with different task types.

Classes

class Task {
    String title;
    public Task(String title) { this.title = title; }
}

class BugTask extends Task {
    int severity;
    public BugTask(String title, int severity) {
        super(title);
        this.severity = severity;
    }
}

class FeatureTask extends Task {
    String feature;
    public FeatureTask(String title, String feature) {
        super(title);
        this.feature = feature;
    }
}

Processing with pattern matching

public static void processTask(Task t) {
    if (t instanceof BugTask bug) {
        System.out.println("Bug: " + bug.title + ", severity: " + bug.severity);
    } else if (t instanceof FeatureTask feature) {
        System.out.println("Feature: " + feature.title + ", module: " + feature.feature);
    } else if (t instanceof Task task) {
        System.out.println("Regular task: " + task.title);
    }
}

7. Useful nuances

Table: Pattern Matching for instanceof — pros and cons

Pros Cons/limitations
Less code, better readability Requires Java 16+
No risk of ClassCastException The variable is visible only inside the if block
Type safety at compile time Does not work for multiple types in a single condition
Convenient for working with inheritance May not be supported in older IDEs and builds
Suitable for any classes

Visual diagram: how pattern matching for instanceof works

+---------------------------+
|      Object obj           |
+---------------------------+
            |
            v
  if (obj instanceof Type t)
            |
      Yes          No
   (true)        (false)
    |               |
    v               v
 t is available  t does not exist
   (code)           (no access)

8. Common mistakes when using pattern matching for instanceof

Mistake #1: Trying to use the variable outside the if block. You declared the variable in the pattern, exited the block — the variable no longer exists. The compiler rightly complains: “What is s?”

Mistake #2: Expecting instanceof to work with null. If the object is null, the instanceof condition is always false, the variable isn’t created. Handle null separately if needed.

Mistake #3: Using the new syntax on an older JDK/IDE. On Java 11 and below, pattern matching for instanceof isn’t available — you’ll get a syntax error. Check your JDK version.

Mistake #4: Confusion about scope. The variable from the pattern is available only in the branch where the check is true. Outside of it — it doesn’t exist.

Mistake #5: Expecting multiple types at once. You can’t declare two variables of different types in one condition: if (obj instanceof String s || obj instanceof Integer i) — not allowed. Each type needs its own check.

1
Task
JAVA 25 SELF, level 65, lesson 1
Locked
Intelligent Data Analyzer 🔍
Intelligent Data Analyzer 🔍
1
Task
JAVA 25 SELF, level 65, lesson 1
Locked
Pet identification at the shelter 🐾
Pet identification at the shelter 🐾
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION