Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java 21 — New Features

Data-Oriented Programming

  • Records
  • Sealed Classes
  • Pattern Matching

Virtual Threads (Project Loom)

  • Virtual Threads
Chaturmind
← Java 21 — New Features

Data-Oriented Programming

  • Records
  • Sealed Classes
  • Pattern Matching

Virtual Threads (Project Loom)

  • Virtual Threads
HomeLearnJavaJava 21 New FeaturesJava 21 Features
✓ FreeIntermediate· 11 min read

Sealed Classes

Use sealed classes and interfaces to define closed type hierarchies and exhaustive pattern matching.

Published February 25, 2025


Sealed Classes (Java 17+)

Sealed classes let you restrict which classes can extend or implement a class/interface. Combined with pattern matching, they enable exhaustive type-safe processing of a closed set of variants — similar to Rust enums or Kotlin sealed classes.

Declaring a Sealed Class

// The sealed class lists its permitted subtypes
public sealed class Shape
    permits Circle, Rectangle, Triangle {
    public abstract double area();
}

// Each permitted type must be: final, sealed, or non-sealed
public final class Circle extends Shape {
    public Circle(double radius) { this.radius = radius; }
    private final double radius;
    public double area() { return Math.PI * radius * radius; }
}

public final class Rectangle extends Shape {
    public Rectangle(double w, double h) { this.width = w; this.height = h; }
    private final double width, height;
    public double area() { return width * height; }
}

public non-sealed class Triangle extends Shape {
    // non-sealed: allows further extension by anyone
    public double area() { return 0; /* simplified */ }
}

Sealed Interfaces

public sealed interface Result<T>
    permits Result.Success, Result.Failure {

    record Success<T>(T value) implements Result<T> {}
    record Failure<T>(String error, Throwable cause) implements Result<T> {}
}

// Usage
Result<User> result = userService.findUser(id);
if (result instanceof Result.Success<User> s) {
    return s.value();
} else if (result instanceof Result.Failure<User> f) {
    throw new RuntimeException(f.error());
}

Pattern Matching with switch (Java 21)

Sealed classes enable exhaustive switch expressions — the compiler verifies all permitted types are handled.

public double calculateArea(Shape shape) {
    return switch (shape) {
        case Circle c     -> Math.PI * c.radius() * c.radius();
        case Rectangle r  -> r.width() * r.height();
        case Triangle t   -> 0.5 * t.base() * t.height();
        // No default needed! Compiler knows all subtypes.
    };
}

If you add a new permitted type to Shape, the compiler forces you to handle it in every exhaustive switch — preventing missed cases.

Domain Modeling with Sealed Classes

// Payment types as a sealed hierarchy
public sealed interface Payment
    permits CreditCard, BankTransfer, Crypto {

    record CreditCard(String cardNumber, String cvv) implements Payment {}
    record BankTransfer(String iban, String bic) implements Payment {}
    record Crypto(String walletAddress, String currency) implements Payment {}
}

// Exhaustive processing
public void processPayment(Payment payment) {
    switch (payment) {
        case CreditCard cc -> chargeCard(cc.cardNumber(), cc.cvv());
        case BankTransfer bt -> initTransfer(bt.iban(), bt.bic());
        case Crypto crypto  -> sendCrypto(crypto.walletAddress(), crypto.currency());
    }
}

Rules

  • Permitted classes must be in the same package (or same module)
  • Each permitted subtype must be final, sealed, or non-sealed
  • non-sealed reopens the hierarchy — useful for extension points

Interview Tips

  1. Sealed classes + pattern matching is the Java answer to algebraic data types (ADTs) in functional languages.
  2. The key benefit: exhaustiveness — the compiler tells you when you've missed a case.
  3. Great for modeling domain events, result types, or state machines.

Previous

Records

Next

Pattern Matching

AI Tutor

Lesson: Sealed Classes

Quick actions

AI responses can be inaccurate. Verify critical information.