Exhaustive switch on Sealed
Compile-time completeness.
Exhaustive switch on Sealed is a free Java Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Exhaustive switch
When you switch over a sealed type, the compiler knows every permitted subtype. If your switch covers them all, it is exhaustive and you do not need a default branch.
A Type Pattern switch
Switch expressions can match on the runtime type of a sealed value using type patterns.
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String describe(Shape s) {
return switch (s) {
case Circle c -> "circle r=" + c.radius();
case Square sq -> "square s=" + sq.side();
};
}
public static void main(String[] args) {
System.out.println(describe(new Circle(2)));
System.out.println(describe(new Square(3)));
}
}No default Needed
Because Circle and Square are the only permitted subtypes, the compiler accepts the switch as complete. Adding a default would be redundant.
Compile-Time Completeness
If you add a new permitted subtype later and forget to handle it, every exhaustive switch fails to compile. This turns a whole class of runtime bugs into compile errors.
Computing a Result
Exhaustive switch expressions are great for folding a value to a result like area.
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Square sq -> sq.side() * sq.side();
};
}
public static void main(String[] args) {
System.out.printf("%.2f%n", area(new Circle(1)));
System.out.printf("%.2f%n", area(new Square(2)));
}
}Switch Statements vs Expressions
Exhaustiveness applies to switch expressions (those that yield a value) and to switch statements that use the arrow form on a sealed type. The compiler enforces full coverage.
Handling null
By default a switch on a reference throws NullPointerException if the value is null. You can add a case null label to handle it explicitly.
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String describe(Shape s) {
return switch (s) {
case null -> "no shape";
case Circle c -> "circle";
case Square sq -> "square";
};
}
public static void main(String[] args) {
System.out.println(describe(null));
System.out.println(describe(new Circle(1)));
}
}Guards Do Not Break Exhaustiveness
You can add when guards to refine cases, but a guarded case alone does not make a type covered. You still need an unguarded case for each subtype to stay exhaustive.
public class Main {
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}
static String size(Shape s) {
return switch (s) {
case Circle c when c.radius() > 10 -> "big circle";
case Circle c -> "small circle";
case Square sq -> "square";
};
}
public static void main(String[] args) {
System.out.println(size(new Circle(20)));
System.out.println(size(new Circle(2)));
}
}Switching on a sealed class
The same exhaustiveness works for sealed classes, not just interfaces.
public class Main {
sealed static abstract class Token permits Word, Number {}
static final class Word extends Token { final String text; Word(String t){text=t;} }
static final class Number extends Token { final int value; Number(int v){value=v;} }
static String show(Token t) {
return switch (t) {
case Word w -> "word:" + w.text;
case Number n -> "num:" + n.value;
};
}
public static void main(String[] args) {
System.out.println(show(new Word("hi")));
System.out.println(show(new Number(7)));
}
}Why This Is Powerful
Exhaustive switch plus sealed types gives you safe, evolvable code. The set of cases is documented in one place, and the compiler guarantees you never miss one when the model grows.
A Complete Example
Here a sealed result type is folded into a message with full coverage.
public class Main {
sealed interface Result permits Ok, Err {}
record Ok(int value) implements Result {}
record Err(String message) implements Result {}
static String render(Result r) {
return switch (r) {
case Ok ok -> "value = " + ok.value();
case Err err -> "error: " + err.message();
};
}
public static void main(String[] args) {
System.out.println(render(new Ok(10)));
System.out.println(render(new Err("bad input")));
}
}Quick Check
Test your understanding of exhaustive switch.
Recap
You learned exhaustive switch on sealed types.
- Covering all permitted subtypes makes the switch exhaustive, so no
defaultis needed. - Missing a new subtype becomes a compile error.
case nullhandles nulls explicitly.- Guards refine but do not replace an unguarded case.
Frequently asked questions
Is the “Exhaustive switch on Sealed” lesson free?
Yes — the full text of “Exhaustive switch on Sealed” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Exhaustive switch on Sealed”?
Compile-time completeness. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Exhaustive switch on Sealed” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Declaring Sealed Types
- permits Clause
- Sealed with Records
- Exhaustive switch on Sealed