sealed classes | code2java

Sealed Classes in Java – Complete Guide with Real-World Examples

πŸ“š Table of Contents

  • What are Sealed Classes?
  • Why Sealed Classes are Needed (Deep Dive)
  • When Were They Introduced?
  • How Sealed Classes Work Internally
  • Types of Permitted Classes
  • Real-World Case Studies
  • Implementation in Java (Code Examples)
  • Sealed Classes with Records
  • Pattern Matching with Sealed Classes
  • Best Practices
  • When NOT to Use Sealed Classes
  • Summary
  • Interview Questions

🧠 What are Sealed Classes?

Sealed classes let you restrict which classes can extend or implement them.

public sealed class Shape permits Circle, Rectangle {
}

Only Circle and Rectangle can extend Shape.

❓ Why Sealed Classes are Needed (Deep Dive)

Before sealed classes:

  • final blocks inheritance
  • abstract allows anyone to extend

Real-world systems need more control than this.

Controlled Inheritance Explained

Controlled inheritance means you define exactly which classes can extend your class.

Without Sealed Classes

abstract class Payment {
}
class CreditCard extends Payment {}
class UPI extends Payment {}
class CryptoPayment extends Payment {} // unexpected

Problems:

  • Any developer can add new subclasses
  • The system can behave unpredictably

With Sealed Classes

public sealed class Payment permits CreditCard, UPI {
}
final class CreditCard extends Payment {}
final class UPI extends Payment {}
class CryptoPayment extends Payment {} // Compile-time error

Now your design stays controlled and predictable.

How Code Readability Improves

public sealed class Shape permits Circle, Rectangle, Triangle {
}

When you read this:

  • You see all possible types immediately
  • You understand the complete hierarchy
  • You don’t need to search the codebase

This approach makes your code self-explanatory.

Business Logic Clarity Example

Without sealed classes:

if (payment instanceof CreditCard) {
    // logic
} else if (payment instanceof UPI) {
    // logic
} else {
    // fallback for unknown types
}

You must handle unknown cases because new subclasses can appear.

With sealed classes:

return switch (payment) {
    case CreditCard cc -> "Processing card";
    case UPI upi -> "Processing UPI";
};

The compiler checks all cases. You don’t need a default branch.

πŸ“… When Were Sealed Classes Introduced?

  • Java 15 introduced them as a preview
  • Java 16 refined them
  • Java 17 made them stable (LTS)

βš™οΈ How Sealed Classes Work Internally

Follow these rules:

  1. Use the sealed keyword
  2. Define allowed subclasses with permits
  3. Each subclass must declare one of:
    • final
    • sealed
    • non-sealed

🧩 Types of Permitted Classes

Final Class

final class Circle extends Shape {}

This class cannot be extended further.

Sealed Class

sealed class Rectangle extends Shape permits Square {}

This class continues to control its hierarchy.

Non-Sealed Class

non-sealed class Triangle extends Shape {}

This class allows further inheritance again.

🌍 Real-World Case Studies

Payment System

Requirement: Allow only specific payment methods.

public sealed interface Payment permits CreditCard, UPI, Cash {
    String process();
}

final class CreditCard implements Payment {
    public String process() {
        return "Processing Credit Card";
    }
}

final class UPI implements Payment {
    public String process() {
        return "Processing UPI";
    }
}

final class Cash implements Payment {
    public String process() {
        return "Processing Cash";
    }
}

Benefits:

  • Developers cannot introduce unexpected payment types
  • Business logic stays consistent

Order State Machine

Orders follow a fixed set of states.

public sealed interface OrderState 
    permits Created, Shipped, Delivered, Cancelled {
}
record Created() implements OrderState {}
record Shipped() implements OrderState {}
record Delivered() implements OrderState {}
record Cancelled() implements OrderState {}

This design helps you:

  • Keep states finite
  • Prevent invalid states
  • Model workflows clearly

API Response Wrapper

A common backend pattern.

public sealed interface ApiResponse<T> 
    permits Success, Error {
}
public record Success<T>(T data) implements ApiResponse<T> {}
public record Error<T>(String message) implements ApiResponse<T> {}

Usage:

static String handle(ApiResponse<String> response) {
    return switch (response) {
        case Success<String> s -> "Data: " + s.data();
        case Error<String> e -> "Error: " + e.message();
    };
}

You cover all cases without a default branch.

πŸ’» Implementation in Java (Mixed Example)

public sealed class Vehicle permits Car, Bike {
    public abstract void drive();
}

final class Car extends Vehicle {
    public void drive() {
        System.out.println("Driving Car");
    }
}

non-sealed class Bike extends Vehicle {
    public void drive() {
        System.out.println("Driving Bike");
    }
}

class SportsBike extends Bike {
    public void drive() {
        System.out.println("Driving Sports Bike");
    }
}

This example balances control and flexibility.

πŸ”— Sealed Classes with Records

This combination works naturally.

public sealed interface Result permits Success, Failure {
}

public record Success(String data) implements Result {}
public record Failure(String error) implements Result {}

Benefits:

  • You get immutable data structures
  • You reduce boilerplate
  • You model domains cleanly

πŸš€ Pattern Matching with Sealed Classes

static String process(Result result) {
    return switch (result) {
        case Success s -> "Data: " + s.data();
        case Failure f -> "Error: " + f.error();
    };
}

The compiler ensures you handle every case.

πŸ’‘ Key Insights

  • Sealed classes make your domain finite and predictable
  • They reduce defensive coding
  • They improve collaboration by making hierarchies explicit
  • They work best with records and pattern matching

❌ When NOT to Use Sealed Classes

Framework or Library Design

Avoid sealed classes if external systems need to extend your code.

Unknown Future Extensions

Do not restrict the hierarchy if new subclasses may appear later.

Overuse

Use sealed classes only when they add clarity and control.

πŸ’‘ Best Practices

  • Keep hierarchies small and meaningful
  • Prefer sealed interfaces when possible
  • Use records for simple data carriers
  • Avoid deep inheritance chains

βœ… Summary

  • Sealed classes control inheritance
  • Java 17 introduced them as a stable feature
  • They improve readability and maintainability
  • They suit domain modeling very well
  • They work effectively with records and pattern matching

🎯 Interview Questions

1. What problem do sealed classes solve?

They provide controlled inheritance.

2. What does the permits clause do?

It defines allowed subclasses.

3. What modifiers must subclasses use?

final, sealed, or non-sealed.

4. How do sealed classes improve switch statements?

They allow exhaustive checks without a default branch.

5. Can you seal an interface?

Yes.

6. When should you avoid sealed classes?

When you design extensible systems.

7. Why combine sealed classes with records?

You get immutable and concise implementations.

To know more about Java 17 features check out – https://code2java.com/jdk-17-features-step-by-step-guide/

Related Posts

  • Abstract Class In JAVA

    Hello Friends, This tutorial is for all the Java followers. One of the best feature that is widely used is the term ‘Abstract’. This term can be used as either class or a simple method. An abstract method is any method that is just declared but not instantiated. In other words one can just create…

  • Threads in Java.

    Hello Friends, This is the tutorial for the java developers. One of the most significance feature of core java is Threading. Threading deals with the processing of Threads in a single java program. Let us learn what actually are Threads. *What are Threads? Threads are independently running processes that are isolated from each other upto…

  • Collections In Java.

    Hello friends, Welcome to another tutorial for java followers. You all may have heard about Collections, it is one of the amazing feature in java. Collections are the object for the group of elements, these elements are nothing but the different data structures like as Array Lists, Linked Lists, Vectors, Hash tables,Hash List, Trees, Hash…

  • Java Date Format.

    Hello Friends, This is one of my tutorials regarding java Date format / object in Java. Many of us find it difficult to store the current date from the java application in database. Lets consider MySql as a database in this case. Now when we create a row in the database table that stores date…

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.