Missing Switch Default
ID |
java.missing_switch_default |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
reliability |
Description
Reports switch statements that do not declare a default clause. Switch expressions (Java 14+) are exempt because the compiler already enforces exhaustiveness.
Rationale
A switch without default silently does nothing when the selector takes an unexpected value. Over time the set of possible values tends to grow — a new enum constant, a new status code, a new wire-level opcode — and every missing default becomes a place where behaviour is implicitly "ignore".
Explicit default has two benefits:
-
It forces the author to decide what happens for unknown values (log, throw, fall-back…).
-
It makes the intent visible to readers: "yes, we thought about it; the correct behaviour is X".
// Bad — silently no-ops for any value other than 1 or 2
switch (code) {
case 1: handleOne(); break;
case 2: handleTwo(); break;
}
Scope
Two further shapes are exempt, both because the compiler has already done this rule’s job and a default would undo it:
-
a pattern switch statement, which the language requires to be exhaustive. Over a sealed hierarchy, adding
defaultis actively harmful: it silences the compile error raised when a new subtype is declared and left unhandled, which is the reason to write the switch that way in the first place; -
a
case null, default →label, which is the default clause even though its first token iscase.
A switch over an enum the software model knows is exempt for a different reason: it belongs to java.switch_on_enum_full_coverage, which can tell a switch that already covers every constant — and so needs no default — from one that does not. An enum the model does not hold, from the JDK or a library, is not one either rule can reason about and stays with this one.
The arrow form on its own is only syntax: a switch statement over a String or an int written with arrows is no more exhaustive than the colon form, and is still reported.
Remediation
Add an explicit default, deciding what an unexpected value should do:
// Good — explicit default
switch (code) {
case 1: handleOne(); break;
case 2: handleTwo(); break;
default:
throw new IllegalArgumentException("unknown code: " + code);
}
Prefer switch expressions when possible — they require exhaustiveness and eliminate this concern at the language level:
return switch (code) {
case 1 -> handleOne();
case 2 -> handleTwo();
default -> throw new IllegalArgumentException("unknown code: " + code);
};