11. Sealed Classes
Sealed classes (Java 17+) restrict which classes can extend or implement them, enabling the compiler to enforce exhaustive switch and model closed type hierarchies.
Java 17+ (standard)Explanation
A sealed class or interface uses the permits clause to list the only allowed direct subtypes. Permitted subtypes must themselves be declared as sealed, non-sealed, or final in the same package (or module). This creates a closed type hierarchy that the compiler understands fully.
The primary payoff is exhaustive switch expressions: when switching over a sealed type, the compiler verifies you've handled every permitted subtype, so no default is needed. Combined with records, sealed types model algebraic data types (sum types) safely.
non-sealed reopens the hierarchy at that subtype, allowing arbitrary further extension. final closes it completely. sealed requires exactly the listed subtypes to exist (they must be in the same compilation unit or module).
Example
public class SealedDemo {
// Sealed interface with three permitted subtypes
sealed interface Result<T> permits Result.Ok, Result.Err, Result.Loading {}
record Ok<T>(T value) implements Result<T> {}
record Err<T>(String msg) implements Result<T> {}
record Loading<T>() implements Result<T> {}
static <T> String describe(Result<T> result) {
// Exhaustive โ no default needed!
return switch (result) {
case Ok<T> ok -> "Success: " + ok.value();
case Err<T> err -> "Error: " + err.msg();
case Loading<T> ign -> "Loading...";
};
}
public static void main(String[] args) {
System.out.println(describe(new Ok<>("Alice")));
System.out.println(describe(new Err<>("Not found")));
System.out.println(describe(new Loading<>()));
// Sealed class with final and non-sealed subtypes
System.out.println("\nGeometry:");
Shape circle = new Circle(5);
Shape rect = new Rectangle(3, 4);
System.out.printf("Circle area: %.2f%n", area(circle));
System.out.printf("Rectangle area: %.2f%n", area(rect));
}
sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double w, double h) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.w() * r.h();
};
}
}Sources
- https://openjdk.org/jeps/409 โ JEP 409: Sealed Classes (standard)
- https://dev.java/learn/sealed-classes/ โ dev.java sealed classes guide