Sealed Classes

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

  • Sealed Classes (Java 17) give you precise control over which classes are allowed to inherit from a class or interface.
  • You use the sealed modifier on the parent, and the permits keyword to list the exact allowed child classes.
  • It is a powerful tool for Domain-Driven Design and pattern matching.

Concept

Before Java 17, inheritance was all-or-nothing. A class was either final (nobody can extend it) or public/protected (literally anyone in the world can extend it).

Imagine you are building a Payment system. You have an interface PaymentMethod. You only want to support CreditCard, PayPal, and BankTransfer. If you make it public, another developer might create a BitcoinPayment class that implements your interface, completely breaking your strict architectural rules.
Sealed classes allow you to lock down the inheritance hierarchy to a known, exhaustive list.

Examples

// 1. Declare the interface as 'sealed'
// 2. Explicitly 'permit' only specific implementations
public sealed interface PaymentMethod 
    permits CreditCard, PayPal, BankTransfer {
    
    void processPayment(double amount);
}

// 3. Allowed subclasses MUST be declared final, sealed, or non-sealed.
public final class CreditCard implements PaymentMethod {
    public void processPayment(double amount) { /* logic */ }
}

public final class PayPal implements PaymentMethod {
    public void processPayment(double amount) { /* logic */ }
}

public final class BankTransfer implements PaymentMethod {
    public void processPayment(double amount) { /* logic */ }
}

// ERROR! Bitcoin is not permitted to implement PaymentMethod!
// public class Bitcoin implements PaymentMethod { } 

Interview Questions

Q: What must a subclass of a sealed class declare?
A: Any class permitted to extend a sealed class MUST declare exactly one of these three modifiers:

  1. final: The hierarchy stops here. Nobody can extend this child class.
  2. sealed: The hierarchy continues, but in a restricted way (this child must have its own permits clause).
  3. non-sealed: The hierarchy is thrown wide open. Anyone can extend this specific child class, effectively breaking the seal for this branch.

Q: How do Sealed Classes improve Pattern Matching in switch statements?
A: Because the compiler knows the exact, exhaustive list of permitted subclasses, you no longer need a default case in modern Java switch expressions!

// The compiler knows there are ONLY 3 possibilities. No default needed!
String msg = switch (paymentMethod) {
    case CreditCard c -> "Processing CC";
    case PayPal p -> "Processing PayPal";
    case BankTransfer b -> "Processing Bank";
};