Sealed Classes and Interfaces

In Java, by default, there is no restriction on a class which public interfaces it can impliment. Since Java 15, now a class or interface can be declared sealed class or sealed interface using the modifier sealed. It is a preview feature in Java 15.

A sealed class or interface restricts which other classes or interfaces may extend or implement them. Conceptually, it is a more declarative way than access modifiers to restrict the use of a class or interface as a parent class or as a parent interface.

A sealed class is a class or interface that restricts which other classes or interfaces may extend.

1. Sealed Classes

1.1. sealed modifier and permits keyword

The sealing of a class or interface can be done using the modifier sealed in the declaration time. Then, after any extends and implements clauses, the permits clause specifies the classes that are permitted to extend the sealed class.

The reserved keyword permits lists all the classes that can extend the sealed class directly. The listed subclasses can either be final, non-sealed, or sealed.

For example, the following declaration of Account specifies three permitted subclasses:

sealed class Account
    permits CurrentAccount, SavingAccount, LoanAccount {
}

final class CurrentAccount extends Account {}
non-sealed class SavingAccount extends Account {}
sealed class LoanAccount extends Account permits HomeloanAccount, AutoloanAccount {}

final class HomeloanAccount extends LoanAccount{}
final class AutoloanAccount extends LoanAccount{}

Here, we are permitted only 3 classes the permission to extend the Account class. No other class class can extend the Account class.

Similarily, only HomeloanAccount and AutoloanAccount are only two supported account types for LoanAccount.

1.2. final, sealed and non-sealed Subclasses

The permitted subclasses must have exactly one of the following modifiers to describe how it continues the sealing initiated by its superclass:

  • final class cannot be extended further.
  • sealed class can only be extended by its permitted subclasses.
  • non-sealed class can be extended by unknown subclasses as well. A sealed class cannot force the sealing behavior to its permitted subclasses.

1.3. Packaging of sealed classes

  • The sealed class and its subclasses, all must be inside the same module.
  • If the given module is a unnamed module then all the classes must be inside the same package.
  • If the permitted classes are written in the same .java file then we can omit the permits keyword.
    public sealed class Account {}		//Omits 'permits' keyword 
    
    final class CurrentAccount extends Account {}
    non-sealed class SavingAccount extends Account {}
    sealed class LoanAccount extends Account {}		//Omits 'permits' keyword 
    
    final class HomeloanAccount extends LoanAccount{}
    final class AutoloanAccount extends LoanAccount{}
    

1.4. Records as sealed classes

We can have a record class in the permits clause of a sealed class or interface.

Record classes are implicitly final and can be used as subclasses of a sealed class.

1.5. APIs Support

Java has added two new methods to support the usage of sealed classes:

    java.lang.constant.ClassDesc[] permittedSubclasses() - It returns an array of ClassDesc objects where each object in array represent a subclass of the sealed class.

  • boolean isSealed() – It returns true if the given class or interface is sealed.

2. Sealed Interfaces

There are not many differences between how a sealed class is defined vs. how a sealed interface is defined. Like sealed classes, to seal an interface, add the sealed modifier to its declaration.

Then, after any extends clause, add the permits clause which specifies the classes that can implement the sealed interface and the interfaces that can extend the sealed interface.

public sealed interface IReport
        permits Printable, Formattable, ExcelReport, PdfReport {
}

non-sealed interface Printable extends IReport {}
non-sealed interface Formattable extends IReport {}
non-sealed class ExcelReport implements IReport {}
non-sealed class PdfReport implements IReport {}

Sealed interfaces follow the same declaration rules as sealed classes.

3. When to use sealed classes?

Remember the use of instanceof operator to test whether the object is an instance of the specified class. Generally, we checked all the possible class types and, at last, in else block, we have to write some code if the given instance doesn’t match any class type.

Also, there is no guarantee that another developer will add one more class to the hierarchy and add the type check in the given instanceof checks. Sealed classes can impose this restriction on the hierarchies at the language level.

With the future direction of instanceof operator and pattern matching, the default block or else block will not be needed.

As soon as a new subclass is added to a sealed class, by using type test patterns, the compiler will be able to check that every permitted subclass is covered.

Happy Learning !!

Leave a Reply

0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.