How do you handle null in a switch pattern matching, and what does case null, default mean?
answer
- no case null => null selector throws NPE (not default)
- case null matches only the null reference
- case null, default = the only legal null pairing
- type patterns mean 'non-null of that type'
- case null not bound by dominance ordering
basics
~20 sA normal pattern case never matches null, so a null selector throws NullPointerException unless you add case null. Writing case null, default means null is handled by the same branch as everything not otherwise matched.
solid answer
~50 sHistorically a switch on a null selector always threw NullPointerException, which forced an explicit null check before the switch. With pattern matching you may add a dedicated case null arm so null is matched inside the switch itself. If the switch has any pattern label but no case null, a null selector still throws NPE (it does not silently fall to default). You can combine null with default in a single arm: case null, default -> ... handles null and all otherwise-unmatched values together; this is the only place null may be paired with another label. Placing case null is allowed anywhere among the labels (it is not subject to dominance the way patterns are), but pairing it with default is the idiomatic way to give null and the catch-all the same behavior. This lets you keep null handling local and visible rather than a separate guard before the switch.
go deeper
Knows that switching on null can throw NPE and that case null is how you handle null inside a switch.
Explains that without case null a null selector throws NPE rather than falling to default, and that case null, default fuses null with the catch-all.
Discusses null as an intentional domain value vs fail-fast design, notes case null is exempt from dominance ordering, and knows null may only be combined with default.
Treats null handling as an API-contract decision (fail-fast vs absorb), and reasons about how explicit case null affects exhaustiveness and downstream callers of a sealed-type switch.
## Background: switch and null For most of Java's history, `switch (x)` where `x` is `null` threw a **NullPointerException (NPE)** immediately — even if a `default` arm existed. The selector was dereferenced (conceptually) to find a matching `case`, and `null` has no value to match. So defensive code wrapped every switch in `if (x == null) { ... } else switch (x) { ... }`. ## case null Pattern matching (Java 21) introduced a new label: **`case null`**. It matches *only* the `null` reference, letting you handle null **inside** the switch: ```java String describe(Object obj) { return switch (obj) { case null -> "nothing"; case String s -> "string of length " + s.length(); default -> "something else"; }; } ``` ### The crucial rule If a switch uses **pattern or null labels** and you do **not** write `case null`, then a `null` selector still throws **NPE** — it does **not** fall through to `default`. This is deliberate: a plain type pattern like `case String s` is meant to mean "a non-null String", so `null` is never quietly swallowed. To handle null you must opt in explicitly. ## case null, default You may merge null with the catch-all in one arm: ```java case null, default -> "null or anything unmatched"; ``` This means: *if the value is null, or if nothing else matched, run this arm*. It is the **only** situation where `null` may be combined with another label in the same `case`. It is handy when null should behave identically to the fallback, while keeping everything inside the switch. ### Terms - **Selector**: the value being switched on. - **NPE (NullPointerException)**: thrown when null is used where an object is required. - **default**: the arm that runs when no other label matched. ## Ordering and dominance `case null` is special: it is not a pattern, so the usual *dominance* ordering (specific-before-general) does not constrain it — you can place it anywhere, though conventionally it goes first or is fused with `default` at the end. It never conflicts with type patterns because only the literal `null` reaches it. ## Practical guidance - If null is a real domain value, give it an explicit `case null` so behavior is intentional and reviewable. - If null should never occur, **omit** `case null`: you then get a fail-fast NPE on bad input rather than a silent default — often the safer choice. - Use `case null, default` only when null genuinely deserves the same treatment as the fallback.
- If a switch expression over an Object has cases for Integer and String plus a default, but no case null, what happens when you pass null?It throws NullPointerException. Without an explicit case null, a null selector is never routed to default; the switch rejects null up front.
saying these in an interview costs you the question
- Claiming a null selector falls through to default automatically — it throws NPE unless case null is present.
- Saying you can write case null, String s — null may only be combined with default, not with other patterns.
- Believing a plain type pattern like case String s also matches null.