skip to content

Which types are allowed as the selector (and case labels) of a traditional Java switch, and which are not?

level: middleimportance: should knowfreq 55%

answer

  1. int/short/byte/char + wrappers
  2. enum and String (Java 7)
  3. No long, float, double, boolean
  4. Labels = unique compile-time constants
  5. String switch is null-unsafe (NPE)

basics

~10 s

You can switch on int and the smaller whole-number types byte, short, char (and their wrapper classes), on enum constants, and on String. You cannot switch on long, float, double, boolean, or arbitrary objects.

solid answer

~40 s

A traditional switch accepts a selector whose type is one of: the integral types int, short, byte, char (plus their boxed wrappers Integer, Short, Byte, Character, which get auto-unboxed), any enum type, or String (added in Java 7). Notably long, float, double, and boolean are not allowed — long because switch is built on 32-bit table/lookup bytecode (tableswitch/lookupswitch), floating point because exact-equality switching is error-prone, and boolean because an if is clearer. The case labels must be compile-time constants assignable to the selector type and must be unique. For enums you write the bare constant name (case MONDAY:), not the qualified Enum.MONDAY. For String the match is .equals-based and case-sensitive, and a null selector throws NullPointerException before any case is considered.

code

java · 23 lines
java
enum Day { MON, TUE, WED }

String classify(Day d) {
    switch (d) {              // enum selector
        case MON:            // unqualified constant
        case TUE:
        case WED:
            return "weekday";
        default:
            return "other";
    }
}

int score(String grade) {
    switch (grade) {         // String selector (Java 7+), case-sensitive
        case "A": return 4;
        case "B": return 3;
        default:  return 0;
    }
}

// long total = ...;
// switch (total) { ... }   // COMPILE ERROR: long not allowed

go deeper

for a junior

Lists the common allowed types (int, char, enum, String) and knows boolean/double are not allowed.

for a middle

Gives the full allowed set including wrappers, knows String arrived in Java 7, and states the case-label constancy/uniqueness rules.

for a senior

Explains the bytecode rationale (tableswitch/lookupswitch, hashCode for String, ordinal for enum) and the null/unboxing NPE pitfalls.

for a principal

Advises on API and style choices — favoring enums for exhaustiveness warnings, guarding null before String switches, and when a polymorphic dispatch beats a switch entirely.

## The allowed selector types The **selector** is the value in `switch (...)`. Java restricts its type to a fixed list: 1. **`int`** — the canonical case. 2. **`byte`, `short`, `char`** — the smaller *integral* (whole-number) types. They are promoted to `int` for the comparison. 3. **The wrapper classes** `Integer`, `Short`, `Byte`, `Character` — these are object boxes around the primitives; Java **auto-unboxes** them. (If a wrapper is `null`, unboxing throws `NullPointerException`.) 4. **`enum` types** — a switch over an enum is very common and lets the compiler warn about unhandled constants. 5. **`String`** — supported since **Java 7**. ## The types that are NOT allowed - **`long`** — even though it is integral. The reason is implementation: the JVM compiles switch into one of two bytecode instructions, **`tableswitch`** (a jump table indexed by value) or **`lookupswitch`** (a sorted key list), both of which key on **32-bit `int`** values. `long` is 64-bit, so it does not fit. - **`float`, `double`** — floating-point equality is imprecise (e.g. `0.1 + 0.2 != 0.3`), so exact-match switching would be a footgun; the language forbids it. - **`boolean`** — there are only two values; an `if/else` is clearer, so it is disallowed. - **Arbitrary reference types** (your own classes, `Object`, etc.) — only `String` and enums are special-cased. (Modern *pattern-matching* switch in recent Java does allow type patterns, but that is the new feature, not the traditional switch.) ## How String and enum switching work under the hood - **String**: the compiler generates code that first switches on `String.hashCode()` (an `int`) and then confirms with `.equals` to defeat hash collisions. Consequences you must know: matching is **value-based and case-sensitive**, and a **`null` selector throws `NullPointerException`** because `.hashCode()` is called on it. - **enum**: you write the **unqualified** constant name in the label — `case MONDAY:`, not `case Day.MONDAY:` — because the selector type already fixes the enum. Internally the compiler switches on each constant's `ordinal()`. ## Rules on the case labels themselves Regardless of type, every case label must be: - a **compile-time constant** (a literal, a `static final` constant of the right type, or an enum constant) — not a variable or a method call; - **assignable to the selector type** (you cannot `case "x":` on an `int` switch); - **unique** within that switch — duplicate labels are a compile error. ## Quick reference table | Type | Allowed? | |------|----------| | `int`, `short`, `byte`, `char` | Yes | | wrappers of the above | Yes (unboxed) | | `enum` | Yes | | `String` | Yes (Java 7+) | | `long` | No | | `float`, `double` | No | | `boolean` | No | | other objects | No (traditional switch) |

  • Why is long not allowed even though it is an integral type?
    switch compiles to tableswitch/lookupswitch bytecode that keys on 32-bit int values; long is 64-bit and does not fit those instructions.
  • What happens if a String switch selector is null?
    It throws NullPointerException, because the generated code calls hashCode()/equals on the selector before matching any case.

saying these in an interview costs you the question

  • Claiming you can switch on long or double
  • Writing case Day.MONDAY instead of case MONDAY for enums
  • Thinking case labels can be runtime variables
  • Forgetting that a null String selector throws NPE

context