Sealed Classes
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
sealedmodifier on the parent, and thepermitskeyword 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:
final: The hierarchy stops here. Nobody can extend this child class.sealed: The hierarchy continues, but in a restricted way (this child must have its ownpermitsclause).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";
};