What are type patterns in a switch, and how do they change what a switch can do compared to a traditional switch?
answer
- case Type var -> ... (test + bind in one)
- Replaces instanceof + cast ladders
- Selector can be any reference type (Object)
- Must be exhaustive (default or all subtypes)
- First matching case in order wins
basics
~20 sA type pattern in a switch case checks whether the value is of a given type and, if so, binds it to a new variable in one step. This lets a switch branch on the runtime type of an object, not just on constants like ints, enums, or strings.
solid answer
~40 sTraditional switch could only test a value against constants (ints, chars, enums, strings) using equality. Type patterns let each case label be a type plus a binding variable, e.g. `case Integer i`. At runtime the switch checks if the selector is an instance of that type; if it is, the value is cast and bound to the named variable, ready to use in that branch. This turns switch into a tool for branching on an object's runtime type, eliminating long `if-else` chains of `instanceof` + cast. It works with the arrow form (`case Integer i -> ...`) so there is no fall-through, and the binding is scoped to its branch. Pattern switches must usually be exhaustive, and the selector can be any reference type, not just the few legacy switch types.
code
java · 8 linesstatic String describe(Object obj) {
return switch (obj) {
case Integer i -> "integer: " + i; // test + bind in one
case String s -> "string of length " + s.length();
case int[] a -> "int array of size " + a.length;
default -> "something else";
};
}go deeper
Knows a type pattern case tests the runtime type and binds a typed variable, replacing instanceof + cast.
Can write an exhaustive pattern switch over an Object, explains arrow form (no fall-through) and per-branch binding scope, and knows order matters.
Articulates exhaustiveness rules, selector-type widening, interaction with sealed types, and migration from instanceof ladders; mentions null behavior.
Frames pattern switch within Java's broader pattern-matching/data-oriented-programming direction (sealed types + records + switch), and reasons about API design and exhaustiveness as a maintainability guarantee.
## Background: what a switch used to be A `switch` is a control-flow statement that picks one branch based on a value (the *selector*). Historically Java's switch could only compare the selector against **constant labels** using equality: integral types (`int`, `byte`, `short`, `char`), their boxed forms, `enum` constants, and (since Java 7) `String`. Each `case` was a constant; the runtime asked "does the selector equal this constant?" ```java switch (day) { // day is an int or enum case MONDAY: ...; break; case TUESDAY: ...; break; } ``` ## What a *pattern* is A **pattern** is a test-and-extract construct: it asks "does this value match a certain shape?" and, if so, **binds** (assigns) part of the value to a variable. The simplest pattern is the **type pattern**: a type name followed by a variable name, e.g. `Integer i`. Matching a value `v` against the type pattern `Integer i` means: *is `v` an instance of `Integer`? If yes, declare a variable `i` of type `Integer` and assign `v` to it.* This is exactly what `instanceof` pattern matching does: ```java if (obj instanceof Integer i) { // tests AND binds i use(i); // i is in scope here } ``` ## Type patterns inside switch Pattern matching in switch (finalized in Java 21) lets a `case` label be a **type pattern** instead of a constant: ```java static String describe(Object obj) { return switch (obj) { case Integer i -> "int " + i; // matches if obj is an Integer; binds i case String s -> "string " + s; // binds s case int[] a -> "array len " + a.length; default -> "other"; }; } ``` At runtime the switch evaluates the cases **in order**; the first whose type pattern the selector is an instance of wins. The matched value is cast to that type and bound to the case's variable, which is then usable in that branch only. ## Why this matters Without it, branching on runtime type meant a chain of `instanceof` + cast: ```java if (obj instanceof Integer) { Integer i = (Integer) obj; ... } else if (obj instanceof String) { String s = (String) obj; ... } ``` The pattern switch replaces this with a single, exhaustive, readable structure and removes the redundant casts. ## Key rules that come with it - **Exhaustiveness:** a switch that uses patterns (or has a result, like a switch *expression*) must cover all possible inputs. If you do not list every type, you must add a `default` (or, for sealed hierarchies, all permitted subtypes). The compiler enforces this. - **The selector type widens:** the selector may be any reference type (e.g. `Object`), not just the legacy switch types. - **Arrow form:** `case Label -> expr;` has no fall-through and scopes bindings to the branch. The old colon form (`case Label:`) still exists but is more error-prone with patterns. - **null:** a pattern switch does **not** silently accept `null`; by default `null` throws `NullPointerException` unless you add `case null` (covered separately). ## Deriving an answer From first principles: switch = pick a branch by value; a type pattern = "is it this type, and if so give me a typed variable"; combine them = a switch that branches on runtime type and hands you a ready-to-use, correctly-typed variable in each branch, replacing `instanceof`/cast ladders.
- Does a pattern switch need to be exhaustive, and what happens if it is not?Yes. A switch that uses patterns (and any switch expression) must cover all inputs. If it does not list every possibility, the compiler requires a `default` (or all permitted subtypes of a sealed type); otherwise it is a compile error.
- Is the bound variable visible outside its case?No. With the arrow form the binding is scoped to that single branch, so different cases can reuse the same name and there is no leakage.
saying these in an interview costs you the question
- Thinking switch can still only handle int/enum/String — patterns allow any reference type
- Forgetting the binding variable is typed and scoped to its branch
- Assuming you still need a manual cast after the case matches
- Believing case order does not matter (it does — first match wins)