Skip to content

Lesson 06 · Sealed Types

Objectives

After this lesson you will be able to:

  • Declare sealed classes/interfaces with a permits clause.
  • Apply the rule that each permitted subtype is final, sealed, or non-sealed.
  • Combine sealed hierarchies with records for exhaustive switch.

sealed and permits

A sealed type restricts which types may extend or implement it, making the hierarchy closed and known to the compiler.

java
sealed interface Shape permits Circle, Square { }

record Circle(double r) implements Shape { }      // final (records are final)
final class Square implements Shape {
    final double side;
    Square(double side) { this.side = side; }
}

Every permitted subtype must itself choose one of:

  • final — no further subclassing (records are automatically final),
  • sealed — continues the closed hierarchy with its own permits,
  • non-sealed — re-opens that branch to any subclass.
java
sealed class Vehicle permits Car, Truck { }
final class Car extends Vehicle { }
non-sealed class Truck extends Vehicle { }        // anyone may extend Truck

Exam trap

A permitted subtype that is none of final/sealed/non-sealed does not compile. Permitted subtypes must be in the same module (or same package if unnamed). If they're declared in the same file, the permits clause may be omitted (the compiler infers it).

Exhaustive switch with sealed types

Because the compiler knows the complete set of subtypes, a switch over a sealed type can be exhaustive without a default — and the compiler errors if you miss a case or add a new subtype later.

java
double area(Shape s) {
    return switch (s) {
        case Circle c -> Math.PI * c.r() * c.r();
        case Square sq -> sq.side() * sq.side();
        // no default needed — Circle and Square exhaust Shape
    };
}

SDET note

Sealed + records + exhaustive switch turn "did I handle every case?" into a compile-time check. Add a new permitted subtype and every non-exhaustive switch fails to compile — the compiler becomes a regression test for missing branches.

Beyond the exam

Sealed types pair with record patterns and guarded case labels (Lesson 08) to model algebraic data types — a powerful idiom, fully on the 1Z0-830 as of Java 21.

Key Takeaways

  • sealed … permits A, B closes a hierarchy to a known set; the permits clause may be omitted when subtypes share the file.
  • Each permitted subtype must be final, sealed, or non-sealed — otherwise a compile error.
  • Permitted subtypes live in the same module/package.
  • A switch over a sealed type can be exhaustive without default; missing a subtype is a compile error — great for catching unhandled cases.

Lesson Quiz

Lesson Quiz · Sealed Types0 / 4
  1. A permitted subtype of a sealed type must be...

    • Apublic
    • Bfinal, sealed, or non-sealed
    • Cabstract
    • Da record
  2. When can the permits clause be omitted?

    • ANever
    • BWhen all permitted subtypes are in the same source file
    • CWhen the type is public
    • DWhen there is only one subtype
  3. Why can this switch omit default?

    sealed interface S permits A, B {}
    // switch over an S handling case A, case B
    • Adefault is always optional
    • BThe compiler knows A and B are the only subtypes (exhaustive)
    • CS is an interface
    • DIt can't — default is required
  4. What does non-sealed mean?

    • ASeals the type further
    • BRe-opens that branch to any subclass
    • CMakes the type final
    • DRemoves it from the hierarchy

Next: Nested & Inner Classes. Run the matching code in labs/src/main/java/com/jse21/m03_oop/.