Exhaustive switch without default
Compiler verifies all sealed subtypes are covered — no default needed.
Code Comparison
✕ Java 8
// Must add default even though
// all cases are covered
double area(Shape s) {
if (s instanceof Circle c)
return Math.PI * c.r() * c.r();
else if (s instanceof Rect r)
return r.w() * r.h();
else throw new IAE();
}
✓ Java 21+
// sealed Shape permits Circle, Rect
double area(Shape s) {
return switch (s) {
case Circle c ->
Math.PI * c.r() * c.r();
case Rect r ->
r.w() * r.h();
}; // no default needed!
}
Why the modern way wins
Compile-time safety
Add a new subtype and the compiler shows every place to update.
No dead code
No unreachable default branch that masks bugs.
Algebraic types
Sealed + records + exhaustive switch = proper ADTs in Java.
Old Approach
Mandatory default
Modern Approach
Sealed Exhaustiveness
Since JDK
21
Difficulty
intermediate
JDK Support
Exhaustive switch without default
Available
Widely available since JDK 21 LTS (Sept 2023)
How it works
When switching over a sealed type, the compiler knows all possible subtypes and verifies every case is handled. If you add a new subtype, the compiler flags every switch that's now incomplete.