Memra

Sealed classes & interfaces (Java 17)

◈ 4 cards

sealed permits restricts the hierarchy — enabling exhaustive switch without default.

Closing the inheritance door — selectively

A sealed class (or interface) declares the exact set of classes permitted to extend it:

public sealed class Shape
    permits Circle, Rectangle, Triangle { }

public final class Circle extends Shape {
    double radius;
}

public non-sealed class Rectangle extends Shape {  // anyone can extend Rectangle
    int width, height;
}

public sealed class Triangle extends Shape
    permits EquilateralTriangle, RightTriangle { }  // Triangle is itself sealed

Every class in the permits list must directly extend the sealed class and must be declared as one of:

  • final — no further extension allowed.
  • sealed — extends the hierarchy with its own permits list.
  • non-sealed — reopens the hierarchy; anyone can extend it.

Exhaustive switch — the payoff

Because the compiler knows every possible subtype, a switch expression can be exhaustive without a default branch:

String desc = switch (shape) {
    case Circle c      -> "circle r=" + c.radius;
    case Rectangle r   -> "rect " + r.width + "x" + r.height;
    case Triangle t    -> "triangle";
    // no default needed — all permitted subtypes covered
};

This enables the pattern switch (Java 21 feature preview in 17) to verify completeness at compile time — catching missed subtypes rather than silently falling through to an unexpected branch at runtime.

Shapesealed permitsCirclefinalRectanglenon-sealedTrianglesealed, permits 2
Every permitted subclass must pick one of the three words — that is what keeps the set of subtypes knowable. Because the compiler can enumerate them, a switch over Shape needs no default branch.
NORMAL ~/memra/learn/java-from-zero/sealed-classes utf-8 LF