BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ OOP and types

Java language

Pattern matching with instanceof

if (o instanceof String s) tests the type and gives you a ready-cast variable s in one step.

Learn these first

At a glance

Mental model

A security guard who not only checks "are you a courier?" but also hands you the courier badge to wear for the rest of the visit.

What happens, in order
  1. 1Old style: if (o instanceof String) { String s = (String) o; ..}. New style: if (o instanceof String s) { ... s.length() ... }. No cast, no repeated type.
  2. 2The variable s exists only where the compiler can prove the test succeeded: inside the if, or after an early exit such as if (!(o instanceof String s)) return;
  3. 3Record patterns deconstruct a record and match nested types in one go: if (shape instanceof Line(Point(var x1, var y1), Point p2))
  4. 4The same patterns work in switch cases, with when guards: case Integer i when i > 10 -> ...
Remember
Watch out
Using the pattern variable outside its scopeReassigning the pattern variable and confusing readersReplacing a clean polymorphic method call with a chain of instanceof tests
Example (highlighted lines explain it)
public class Describer {  static String describe(Object o) {    if (o instanceof String s && !s.isEmpty()) return "text of " + s.length();    if (o instanceof Integer i) return "number " + (i + 1);    return "something else";  }}
Read the full explanation (about 1 min)

if (o instanceof String s) tests the type and gives you a ready-cast variable s in one step. Record patterns go further and take an object apart: o instanceof Point(int x, int y).

A mental model

A security guard who not only checks "are you a courier?" but also hands you the courier badge to wear for the rest of the visit.

How it works

Old style: if (o instanceof String) { String s = (String) o; ... }. New style: if (o instanceof String s) { ... s.length() ... }. No cast, no repeated type.

The variable s exists only where the compiler can prove the test succeeded: inside the if, or after an early exit such as if (!(o instanceof String s)) return;.

Record patterns deconstruct a record and match nested types in one go: if (shape instanceof Line(Point(var x1, var y1), Point p2)).

The same patterns work in switch cases, with when guards: case Integer i when i > 10 -> ....

Going deeper

instanceof is false for null, so a pattern never matches null: no NullPointerException from the test itself.

Long chains of instanceof are a smell in object-oriented code: usually a method on the type (polymorphism) or a sealed type with a switch is cleaner. Patterns are best at the boundary, for example in equals or when handling mixed data.

Under the hood

The compiler translates a pattern into the same instanceof and checkcast instructions as before plus a local variable; record patterns call the record's accessor methods in sequence, so any exception inside an accessor surfaces as a MatchException.

Common mistakes

  • Using the pattern variable outside its scope.
  • Reassigning the pattern variable and confusing readers.
  • Replacing a clean polymorphic method call with a chain of instanceof tests.

How Unravel recognises it

When you paste code, Unravel looks for these signs of pattern matching with instanceof. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is Pattern matching with instanceof?

if (o instanceof String s) tests the type and gives you a ready-cast variable s in one step. Record patterns go further and take an object apart: o instanceof Point(int x, int y).

What are the most common mistakes with Pattern matching with instanceof?

Using the pattern variable outside its scope. Reassigning the pattern variable and confusing readers. Replacing a clean polymorphic method call with a chain of instanceof tests.

How can I see Pattern matching with instanceof in real code?

Paste your own Java into Unravel and it will point out where pattern matching with instanceof appears, explain how it works at the detail level you choose, and draw the flow of the code around it.