All topics
library
intermediate

Sealed Classes & Interfaces (Java 17)

Restrict which classes can extend a type — enabling exhaustive pattern matching and controlled hierarchies.

A sealed type names exactly which types may extend it.

Sealed class = an invitation-only club. Only approved members (permitted subtypes) can join. Everyone else is turned away at the door.

Key Concepts

1
    sealed interface Shape permits Circle, Rectangle, Triangle { }
2
    record Circle(double r)            implements Shape { }
    record Rectangle(double w, double h) implements Shape { }
    record Triangle(double b, double h)  implements Shape { }
3
Each permitted subtype must declare its own intent.
    final        no further extension
    sealed       extension restricted again
    non-sealed   deliberately reopened
4
Records are implicitly final, which is why they pair with sealed types so neatly.
5
The payoff is exhaustiveness.
    double area(Shape s) {
      return switch (s) {
        case Circle c    -> Math.PI * c.r() * c.r();
        case Rectangle r -> r.w() * r.h();
        case Triangle t  -> t.b() * t.h() / 2;
      };                             // no default needed
    }
6
The compiler knows the list is complete, so it accepts the switch without a default. And if someone adds a fourth shape, this stops compiling — which is exactly what you want, because it points at every place that needs the new case.
default
7
A default branch would have hidden that. It would compile, run, and silently return the wrong answer.
default
8
Where the subtypes must live. The same module, or the same package if there is no module. That is what lets the compiler trust the list.
9
permits can be omitted when the subtypes are in the same file:
permits
10
    sealed interface Shape { }
    record Circle(double r) implements Shape { }
11
What it gives you beyond switches.
    a hierarchy you can reason about completely
    an API that states which extensions are supported
    sensitive interfaces that cannot be implemented by callers
12
This is Java's version of an algebraic data type — a fixed set of shapes, each with its own data, handled exhaustively. Before sealed types you wrote the visitor pattern to get the same guarantee, with far more code.
13
What the interviewer is probing.1. "What problem do sealed types solve?" Probing: exhaustiveness. Stalls: "They stop people extending things." Moves up: the compiler knows every subtype, so a switch can be exhaustive without a default — and adding a subtype then breaks the build at every place that must change.
14
2. "Why is omitting default in an exhaustive switch better than including it?" Probing: the real benefit. Stalls: "It is shorter." Moves up: a default silently absorbs a new subtype and returns a wrong answer; without it the compiler points at every site that needs updating.
15
3. "What must a permitted subclass declare?" Probing: the rule. Stalls: "Nothing." *Moves up:* final, sealed or non-sealed — so the hierarchy stays closed or is reopened deliberately.
16
4. "How do sealed interfaces relate to the visitor pattern?" Probing: whether you can place it historically. Stalls: "They are unrelated." Moves up: they give the same exhaustiveness guarantee that visitor was invented to provide, with far less code.