What is the instanceof pattern matching feature in Java, and how does it improve on the classic instanceof-then-cast idiom?
answer
- Test and cast in one step
- Type pattern = `Type name`
- Pattern variable already cast
- Java 16, JEP 394
- Foundation for switch/record patterns
basics
~20 sinstanceof pattern matching lets you test a type and bind the value to a typed variable in one step: if (obj instanceof String s) gives you s already cast to String, so you skip the separate, manual cast.
solid answer
~40 sBefore Java 16, you wrote `if (obj instanceof String) { String s = (String) obj; ... }` — a redundant cast that repeats the type and can drift out of sync. The instanceof pattern (a 'type pattern') combines the test and the bind: `if (obj instanceof String s)` declares a pattern variable `s` that the compiler has already cast to String when the test succeeds. It removes the boilerplate cast, eliminates a class of bugs where the cast target diverges from the tested type, and reads more declaratively. The pattern variable is in scope wherever the test is known to be true (flow scoping). It became a standard feature in Java 16 (JEP 394) and is the foundation for record patterns and switch pattern matching.
go deeper
Knows the syntax obj instanceof String s binds an already-cast variable, removing the manual cast.
Explains why it is safer (no type drift between test and cast), that null doesn't match, and that scope follows the true-branch.
Frames it within the pattern-matching family (switch, records), discusses flow scoping precisely, and notes it is compile-time sugar over the same runtime test.
Discusses migration strategy across a large codebase, readability/standardization trade-offs, and how type patterns set up exhaustive switch over sealed hierarchies.
## The problem it solves `instanceof` is Java's operator for asking "is this object an instance of this type?" — it returns a boolean. Historically, after confirming the type you still had to *cast* the object to use it as that type: ```java Object obj = ...; if (obj instanceof String) { // 1. test the type String s = (String) obj; // 2. cast it manually System.out.println(s.length()); } ``` This has two annoyances. First, **redundancy**: you name the type `String` twice. Second, a **correctness trap**: nothing forces the cast target to match the tested type — you could test `instanceof String` but cast to `(CharSequence)`, and the compiler wouldn't complain, so the two can drift apart during refactoring. ## The feature **instanceof pattern matching** (introduced as a preview in Java 14, finalized in Java 16, JEP 394) lets the `instanceof` operator take a **type pattern** instead of just a type. A type pattern is `Type variableName`: ```java if (obj instanceof String s) { // test AND bind in one step System.out.println(s.length()); // s is already a String here } ``` Here `s` is called a **pattern variable** (also called a binding variable). When the runtime test `obj instanceof String` succeeds, the compiler *automatically* casts `obj` to `String` and assigns it to `s`. You never write the cast yourself. ## Why it is safer and cleaner - **No redundant cast** — the type is stated once. - **No drift bug** — the bound variable's type is, by construction, the tested type. - **More declarative** — the code says "if obj is a String called s" rather than "test, then cast". ## Where the variable is usable: flow scoping (preview) The pattern variable is in scope exactly where the compiler can *prove* the match succeeded. In the simple `if` body above, that's the then-branch. This is called **flow scoping** and is the deepest part of the feature (covered in detail in a separate question): the variable's reach follows the program's logical flow, not lexical braces alone. ## Relationship to the broader feature The type pattern in `instanceof` is the first and simplest **pattern**. The same pattern concept later powers **switch pattern matching** (`case String s ->`) and **record patterns** (`case Point(int x, int y) ->`). Learning instanceof patterns is the entry point to all of Java's modern pattern matching. ## Terms recap - **instanceof**: boolean operator testing runtime type. - **Type pattern**: `Type name`, the thing instanceof now accepts. - **Pattern variable / binding variable**: the new variable the pattern introduces, already cast. - **Flow scoping**: the rule deciding where that variable is in scope.
- Does instanceof pattern matching match null?No. Just like classic instanceof, `null instanceof String s` is false, so the pattern variable is never bound for a null value — this is actually a convenient built-in null guard.
- Which Java version made it a standard (non-preview) feature?Java 16 (JEP 394). It was previewed in Java 14 and 15.
saying these in an interview costs you the question
- Saying you still need a manual cast inside the if body
- Claiming it changes runtime behavior (it is the same instanceof test, just sugar plus flow scoping)
- Thinking the pattern variable exists even when the test is false
- Confusing it with generics or with `getClass() ==`