Sealed Classes & Interfaces

A sealed class or interface restricts which other types may extend or implement it to an explicit permits list, giving you a closed, compiler-known hierarchy you can switch over exhaustively.

Learn Sealed Classes & Interfaces in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

You should be comfortable with inheritance , records , and pattern matching for switch . Sealed types are standard from Java 17 .

💡 Analogy: A normal interface is a party with the door wide open — anyone may walk in and implement it. A final class is a locked room nobody can enter. A sealed type is a party with a guest list : only the names on permits get in. Because you know exactly who's at the party, you can plan for everyone — that's why a switch over a sealed type can be complete with no "and anyone else" fallback.

A closed set of possibilities is enormously powerful: the compiler can now prove you've handled every case, and warn you the moment a new guest is added.

Declare the parent sealed and list its implementors with permits . Then a switch that has an arm per permitted subtype is exhaustive — no default required. Records make ideal subtypes because they are implicitly final and carry their data plainly.

Every direct subclass must say how it continues the seal. final closes the branch. sealed keeps restricting with its own permits . non-sealed reopens the branch for unrestricted extension. You must pick one — the compiler won't let a permitted subclass stay ambiguously open.

A sealed parent plus record subtypes models an algebraic data type : a value that is exactly one of a fixed set of shapes. The classic example is an expression tree — an Expr is a number, an addition, or a multiplication — evaluated with a single exhaustive, recursive switch.

Predict the result before opening each answer.

Answer: No. B is a permitted subtype but doesn't declare final , sealed , or non-sealed . error: sealed, non-sealed or final modifiers expected . Mark B as one of them.

Answer: It won't compile — the switch isn't exhaustive because Y isn't handled. The compiler reports the missing case. Add case Y y -> 2; .

Answer: No. Rogue isn't on the permits list, so error: Rogue is not allowed in the sealed interface S . Only listed types may implement a sealed interface.

🎯 Your Turn — A sealed Payment type

Model three payment kinds and describe each with an exhaustive switch (no default ).

🧩 Mini-Challenge — A JSON value ADT

Build a closed set of JSON value variants and render each one exhaustively.

You can now seal a hierarchy with permits , choose final / sealed / non-sealed for each subtype, write exhaustive switches with no default , and model algebraic data types with sealed interfaces and records.

Next up: Record Patterns & Deconstruction — pull a record's components straight out inside a switch.

Practice quiz

What does a sealed class or interface do?

  • Makes a class final
  • Hides all its methods
  • Restricts which classes may extend or implement it
  • Prevents instantiation

Answer: Restricts which classes may extend or implement it. sealed limits the permitted subtypes to an explicit list, controlling the type hierarchy.

Which keyword lists the allowed subtypes?

  • permits
  • allows
  • extends
  • implements

Answer: permits. sealed interface Shape permits Circle, Square {} names the permitted implementors.

What modifiers must a permitted subclass declare?

  • public or private
  • abstract only
  • static
  • final, sealed, or non-sealed

Answer: final, sealed, or non-sealed. Every direct subclass of a sealed type must be final, sealed (with its own permits), or non-sealed.

What does non-sealed do?

  • Makes it final
  • Re-opens a type so anyone can extend it again
  • Hides it
  • Deletes the permits list

Answer: Re-opens a type so anyone can extend it again. non-sealed deliberately lifts the restriction for that branch, allowing unrestricted further subclassing.

In which Java version did sealed classes become standard?

  • Java 17
  • Java 11
  • Java 14
  • Java 21

Answer: Java 17. Sealed classes finalized in Java 17 (JEP 409).

Why is a switch over a sealed type exhaustive without default?

  • Switches never need default
  • Sealed disables default
  • The compiler knows the complete set of permitted subtypes
  • It uses reflection

Answer: The compiler knows the complete set of permitted subtypes. Because permits lists every subtype, the compiler can verify all cases are covered.

Can a permitted subclass live in a different package from the sealed parent (unnamed module)?

  • Always
  • It must be in the same module, and same package if in an unnamed module
  • Never
  • Only if final

Answer: It must be in the same module, and same package if in an unnamed module. Permitted subclasses must be in the same module; in the unnamed module they must share the package.

What happens if you omit a permitted case in an exhaustive switch and later add a subtype?

  • Nothing
  • It silently returns null
  • Runtime crash only
  • The switch becomes non-exhaustive and the compiler flags it

Answer: The switch becomes non-exhaustive and the compiler flags it. Adding a permitted subtype makes existing exhaustive switches incomplete, so the compiler points you to each one.

What is an 'algebraic data type' modelled with sealed + records?

  • A math library
  • A type that is exactly one of a fixed set of shapes
  • A generic collection
  • A thread pool

Answer: A type that is exactly one of a fixed set of shapes. Sealed parent + record subtypes expresses a closed sum type: a value is exactly one of the listed variants.

Can you omit permits when the subclasses are in the same source file?

  • No, permits is always required
  • Only for interfaces
  • Yes — the compiler infers permitted types from that file
  • Only for records

Answer: Yes — the compiler infers permitted types from that file. If all permitted subtypes are declared in the same compilation unit, you may omit the permits clause.