100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is a Sealed Class?

Sealed classes explained — the permits clause, required subclass modifiers, and exhaustive switch pattern matching — with Java 17 examples.

hardQ91 of 226 in Object Oriented Programming Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

A sealed class is a class (or interface) that explicitly restricts which other classes are allowed to extend or implement it, using a “permits” clause naming the exact set of permitted subclasses.

Declared with the “sealed” modifier and a “permits” clause (Java 17+), a sealed class or interface lets the author control the entire inheritance hierarchy rather than leaving it open to any class in any package. Every permitted subclass must itself be declared “final”, "sealed", or “non-sealed” — closing off further extension, continuing the restriction, or explicitly reopening it, respectively. This gives the compiler exhaustive knowledge of every possible subtype, which enables exhaustive “switch” pattern matching without a default branch and lets a fixed, closed set of variants (like a result type of Success/Failure/Pending) be modeled safely. It is the language-level middle ground between a fully open class hierarchy (anyone can extend) and a fully closed one (final, nobody can extend) — you get controlled, known extensibility instead of either extreme.

  • Compiler can verify exhaustive handling of all subtypes in switch expressions
  • Prevents unknown or unintended subclasses from being introduced elsewhere
  • Documents the complete, intentional set of variants directly in the type system
  • Balances extensibility with control, unlike fully open or fully final classes

AI Mentor Explanation

A domestic league explicitly names the only clubs permitted to compete in it — no new club can join simply by declaring itself eligible, it must be on the named list. That named, closed list is exactly what a sealed class's “permits” clause does for subclasses: only the explicitly listed classes may extend it. Anyone reviewing the league rules knows the complete, exhaustive set of competitors in advance, just as a sealed hierarchy lets code exhaustively handle every possible subtype with certainty.

Step-by-Step Explanation

  1. Step 1

    Declare the class sealed

    Add the “sealed” modifier to the base class or interface.

  2. Step 2

    List permitted subclasses

    Add a “permits A, B, C” clause naming every class allowed to extend it.

  3. Step 3

    Qualify each subclass

    Each permitted subclass must be declared final, sealed, or non-sealed.

  4. Step 4

    Use exhaustive pattern matching

    Switch expressions over the sealed type can now omit a default branch, since the compiler knows every possible case.

What Interviewer Expects

  • Correct explanation of the permits clause and its exhaustive-typing purpose
  • Awareness that permitted subclasses must be final, sealed, or non-sealed
  • Understanding of when sealed classes are useful (closed, known variant sets)
  • Contrast with fully open inheritance and with final classes

Common Mistakes

  • Confusing sealed classes with final classes (sealed still allows controlled extension)
  • Forgetting that every permitted subclass must specify final, sealed, or non-sealed
  • Assuming sealed is available in all Java versions (it requires Java 17+)
  • Not recognizing the exhaustive switch-matching benefit as a primary motivation

Best Answer (HR Friendly)

A sealed class lets you explicitly control exactly which other classes are allowed to extend it, by naming them in a permits list, instead of leaving inheritance wide open to anyone. It's useful when you want a fixed, known set of variants — like different states of a result — because the compiler then knows every possible subtype and can check your code handles all of them.

Code Example

Sealed interface with exhaustive switch
public sealed interface Result permits Success, Failure, Pending {}

public final class Success implements Result {
    public final String data;
    Success(String data) { this.data = data; }
}

public final class Failure implements Result {
    public final String error;
    Failure(String error) { this.error = error; }
}

public final class Pending implements Result {}

// Exhaustive switch: compiler knows there are no other cases, no default needed
static String describe(Result r) {
    return switch (r) {
        case Success s -> "OK: " + s.data;
        case Failure f -> "Error: " + f.error;
        case Pending p -> "Still waiting";
    };
}

Follow-up Questions

  • What are the required modifiers for a permitted subclass of a sealed class?
  • How does a sealed class differ from a final class?
  • What Java version introduced sealed classes, and were they preview features first?
  • How do sealed classes interact with exhaustive switch pattern matching?

MCQ Practice

1. What clause does a sealed class use to name its allowed subclasses?

The “permits” clause explicitly lists every class allowed to extend a sealed class or interface.

2. Every permitted subclass of a sealed class must itself be declared as?

Each permitted subclass must specify final (closes extension), sealed (continues restriction), or non-sealed (reopens extension).

3. A major practical benefit of sealed classes with switch expressions is?

Since the compiler knows every permitted subtype, a switch over a sealed type can be checked for exhaustiveness without a default case.

Flash Cards

Sealed class in one line?A class restricting exactly which subclasses may extend it, via a permits clause.

What must permitted subclasses declare?final, sealed, or non-sealed.

Key benefit with switch expressions?Exhaustive handling of all subtypes, no default branch required.

How does it differ from final?final blocks all extension; sealed allows controlled, named extension.

1 / 4

Continue Learning