Java 17 Sealed classes
In this article, we will explore sealed classes, a new feature introduced in java 17, how to declare and use them with examples.
Sealed classes were introduced in java 15 as a preview feature and in java 16, again as a preview feature. Finally, it is included as a feature in java 17 (JEP 409) .
A sealed class allows you to restrict or choose its sub-classes. A class can not extend a sealed class, if it is not in the list of permitted child classes of parent class.
A class is sealed with the use of sealed
keyword. A sealed class must be followed by permits
keyword along with the list of classes that can extend it. Example,
public sealed class Device permits Computer, Mobile { }
This declaration means that Device
can only be extended by Computer
and Mobile
classes. If any other class tries to extend it, then it will be a compiler error.
A class that extends a sealed class must have either final
, sealed
or non-sealed
keyword in its declaration. This way, we have a fixed or known hierarchy of classes.
This is because by making a child class :
1. final means, that it cannot be sub-classed further.
2. sealed
means, that we need to declare child classes with permits
.
3. non-sealed
means, that we are ending the parent-child hierarchy here.
As an example, Computer
permits Laptop
and Desktop
classes, while Laptop
keeps itself non-sealed
.
This means that Laptop can be extended by classes such as Apple
, Dell
, HP
etc.
Main goals behind the introduction of sealed classes are:
1. Till now, you can only restrict a class from being extended using final
keyword. Sealed classes can control which classes can extend it by including them in permitted list.
2. This also allows a class to control which classes will be its children.
Rules
Below are the things you need to remember while using sealed classes.
1. A sealed class must define the classes that may extend it using permits
. This is not required if the child classes are defined inside parent class as an inner class.
2. A child class must either be final
, sealed
or non-sealed
.
3. A permitted child class must extend the parent sealed class.
That is, if sealed class A permits a class B, then B has to extend A.
4. If sealed class is in a module, then child classes must also be in the same module or in the same package, if the parent sealed class is in an unnamed module.
5. Only directly permitted classes can extend a sealed class. That is, if A is a sealed class which permits B to extend it and B is also a sealed class that permits C.
Then C can only extend B, it can not directly extend A.
Similar to sealed classes, interfaces can also be sealed. An interface may allow to choose its child interfaces or classes that can extend it using
permits
.Same rules apply to interfaces as well. Example,
public sealed interface Device permits Electronic, Physical, DeviceImpl { }
Device
interface allows Electronic
and Physical
interfaces to extend it and DeviceImpl
class to implement it.
Sealed records
Sealed classes can be used with records introduced in java 16. A record can not extend a normal class, so it can only implement a sealed interface.
Further, a record is implicitly final. So, it can not use permits keyword since it can not be sub-classed. Thus, there is a single level hierarchy with records. Example,
public sealed interface Device permits Laptop { } public record Laptop(String brand) implement Device { }
Reflection support
Java reflection provides support for sealed classes. Following two methods have been added in java.lang.Class
:
1. getPermittedSubclasses()
It returns an array of java.lang.Class
containing all the classes permitted by this class object. Example,
Device c = new Device(); Class<? extends Device> cz = c.getClass(); Class<?>[] permittedSubclasses = cz.getPermittedSubclasses(); for (Class<?> sc : permittedSubclasses) { System.out.println(sc.getName()); }
This prints
Computer
Mobile
2. isSealed()
It returns true
if the class or interface on which it is called is sealed.