Beginning with JDK 17, it is possible to declare a class that can be inherited by only specific subclasses. Such a class is called sealed. Prior to the advent of sealed classes, inheritance was an “all or nothing” situation. A class could either be extended by any subclass or marked as final, which prevented its inheritance entirely. Sealed classes fall between these two extremes because they enable you to specify precisely what subclasses a superclass will allow.
In similar fashion, it is also possible to declare a sealed interface in which you specify only those classes that implement the interface and/or those interfaces that extend the sealed interface. Together, sealed classes and interfaces give you significantly greater control over inheritance, which can be especially important when designing class libraries.
Sealed Classes
To declare a sealed class, precede the declaration with sealed. Then, after the class name, include a permits clause that specifies the allowed subclasses. Both sealed and permits are context-sensitive keywords that have special meaning only in a class or interface declaration. Outside of a class or interface declaration, sealed and permits are unrestricted and have no special meaning. Here is a simple example of a sealed class:
public sealed class MySealedClass permits Alpha, Beta {
// ...
}
Here, the sealed class is called MySealedClass. It allows only two subclasses: Alpha and Beta. If any other class attempts to inherit MySealedClass, a compile-time error will occur.
public final class Alpha extends MySealedClass {
// ...
}
public final class Beta extends MySealedClass {
// ...
}
Notice that each is specified as final. In general, a subclass of a sealed class must be declared as either final, sealed, or non-sealed.
At first, it might seem a bit surprising, but you can unseal a subclass of a sealed class by declaring it non-sealed. This context-sensitive keyword was added by JDK 17. It unlocks the subclass, enabling it to be inherited by any other class. For example, Beta could be coded like this:
public non-sealed class Beta extends MySealedClass {
// ...
}
Now, any class may inherit Beta. However, the only direct subclasses of MySealedClass remain Alpha and Beta. A primary reason for non-sealed is to enable a superclass to specify a limited set of direct subclasses that provide a baseline of well-defined functionality but allow those subclasses to be freely extended.
If a class is specified in a permits clause for a sealed class, then that class must directly extend the sealed class.
A key requirement of a sealed class is that every subclass that it permits must be accessible. Furthermore, if a sealed class is contained in a named module, then each subclass must also be in the same named module. In this case, a subclass can be in a different package from the sealed class. If the sealed class is in the unnamed module, then the sealed class and all permitted subclasses must be in the same package.
Sealed Interfaces
public sealed interface MySealedIF permits Alpha, Beta {
void myMeth();
}
A class that implements a sealed interface must itself be specified as either final, sealed, or non-sealed.
Here is a key point: Any class specified in a sealed interface’s permits clause must implement the interface. Thus, a sealed interface and its implementing classes form a logical unit. A sealed interface can also specify which other interfaces can extend the sealed interface.
References
For more information on sealed classed and interfaces you can get the information from Java: The Complete Reference, Twelfth Edition 12th Edition by Herbert Schildt






0 Comments