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) .

Sealed classes
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.

Sealed interfaces
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.

That is all on sealed classes added in java 17. Hope the article was informative.