skip to content

Is an instanceof pattern variable effectively final? What happens if you reassign it, and why does that matter?

level: seniorimportance: should knowfreq 35%

answer

  1. Pattern variable = ordinary local, not auto-final
  2. Reassign allowed but discouraged
  3. Reassign → loses effectively-final
  4. Effectively final → capturable by lambdas
  5. Treat as read-only binding

basics

~20 s

A pattern variable behaves like a normal local variable: it isn't automatically final, so you can reassign it, but if you do it stops being effectively final. Most guidance says don't reassign it — treat it as read-only.

solid answer

~40 s

A pattern variable is a regular local variable, not implicitly final. Technically you can reassign it after it's bound, but doing so is strongly discouraged and the JLS treats it like any other local for the effectively-final rule: assign it once and it is effectively final, which means it can be captured by a lambda or anonymous class and used in nested contexts. If you reassign it, it loses effectively-final status and can no longer be captured, and worse, you've decoupled the variable from the matched value, defeating the whole point of the pattern. The practical rule: treat pattern variables as read-only bindings of the matched object. Keeping them effectively final preserves their usability inside lambdas and keeps the code's intent clear.

go deeper

for a junior

Knows a pattern variable can be used like a normal variable and that it's best not to change it.

for a middle

Explains that it isn't implicitly final, that reassigning loses effectively-final status, and that you should treat it as read-only.

for a senior

Connects effectively-final to lambda/anonymous-class capture rules and articulates why reassignment defeats the pattern's intent.

for a principal

Sets team conventions (e.g. never reassign, optionally mark final), and reasons about interaction with closures in stream-heavy code and code-review automation.

## Background: 'final' vs 'effectively final' A local variable is **final** if declared with the `final` keyword — it can be assigned exactly once. A variable is **effectively final** if it is *never reassigned* after initialization, even though it isn't declared `final`. Java requires that any local variable captured by a **lambda** or **anonymous inner class** be final or effectively final (because the capture copies the value; allowing mutation would be ambiguous about which value is seen). ## How this applies to pattern variables An instanceof pattern variable (e.g. the `s` in `obj instanceof String s`) is, by design, **a normal local variable**. It is *not* implicitly `final`. That means the language *permits* reassigning it: ```java if (obj instanceof String s) { s = s.trim(); // legal, but now s is no longer effectively final } ``` But once you reassign it, it is no longer **effectively final**, with two consequences: 1. **It can no longer be captured** by a lambda or anonymous class declared after the reassignment — the compiler will reject the capture, exactly as for any reassigned local. 2. **You've broken the binding's meaning.** The whole value of the pattern is that `s` *is* the matched object. Reassigning it makes `s` point at something else, so the name no longer reliably means "the matched String," which is confusing and bug-prone. ## Why effectively-final matters in practice Pattern matching often appears in code that also uses streams and lambdas: ```java if (obj instanceof List<?> list) { list.forEach(e -> process(e, list)); // capturing 'list' needs it effectively final } ``` If you never reassign `list`, it stays effectively final and can be captured freely. This is why the recommended discipline — and what most code review rubrics enforce — is to **treat pattern variables as read-only**. Some teams even add `final` to make the intent explicit, though it's redundant when you simply never reassign. ## Summary of the rule - Pattern variable = ordinary local, **not** auto-final. - Don't reassign it; keep it effectively final. - Effectively final → capturable by lambdas/inner classes and faithful to the matched value. - Reassigning it is legal but loses capturability and obscures intent. ## Terms recap - **final variable**: assigned exactly once, enforced by keyword. - **effectively final**: never reassigned, so it behaves like final without the keyword. - **capture**: a lambda/anonymous class reading an enclosing local; requires (effectively) final. - **pattern variable**: the binding introduced by a type pattern; an ordinary local by design.

  • Can you declare a pattern variable as `final`?
    Yes — `if (obj instanceof final String s)` is allowed and documents that you won't reassign it. It's optional because simply never reassigning already makes it effectively final.
  • Why does lambda capture require effectively final variables?
    Captured locals are effectively copied into the lambda; if the original could change afterward, it would be ambiguous which value the lambda sees, and there's no shared mutable cell. Requiring final/effectively-final removes that ambiguity.

saying these in an interview costs you the question

  • Claiming pattern variables are implicitly final and cannot be reassigned
  • Saying reassignment is a compile error (it's legal, just unwise)
  • Not knowing why effectively-final matters (lambda capture)
  • Thinking reassignment changes the matched object somehow

context