Java Sealed Classes
What is Sealed Classes?
A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so.
A class is sealed by applying the sealed modifier to its declaration. Then, after any extends and implements clauses, the permits clause specifies the classes that are permitted to extend the sealed class.
The classes specified by permits must be located near the superclass: either in the same module (if the superclass is in a named module) or in the same package (if the superclass is in the unnamed module).
For example,
-
permits class and sealed class are in same module
-
permits class and sealed class are not in same module
Sealing a class restricts its subclasses. User code can inspect an instance of a sealed class with an if-else chain of instanceof tests, one test per subclass; no catch-all else clause is needed. For example, the following code looks for the three permitted subclasses of Shape:
Shape rotate(Shape shape, double angle) { if (shape instanceof Circle) return shape; else if (shape instanceof Rectangle) return shape.rotate(angle); else if (shape instanceof Square) return shape.rotate(angle); // no else needed! }
A sealed class imposes three constraints on its permitted subclasses:
-
The sealed class and its permitted subclasses must belong to the same module, and, if declared in an unnamed module, to the same package.
-
Every permitted subclass must directly extend the sealed class.
-
Every permitted subclass must use a modifier to describe how it propagates the sealing initiated by its superclass:
-
A permitted subclass may be declared final to prevent its part of the class hierarchy from being extended further. (Record classes (JEP 395) are implicitly declared final.)
-
A permitted subclass may be declared sealed to allow its part of the hierarchy to be extended further than envisaged by its sealed superclass, but in a restricted fashion.
-
A permitted subclass may be declared non-sealed so that its part of the hierarchy reverts to being open for extension by unknown subclasses. (A sealed class cannot prevent its permitted subclasses from doing this.)
-
Sealed interfaces
As for classes, an interface can be sealed by applying the sealed modifier to the interface. After any extends clause to specify superinterfaces, the implementing classes and subinterfaces are specified with a permits clause.
For example,
sealed interface Celestial
permits Planet, Star, Comet { ... }
final class Planet implements Celestial { ... }
final class Star implements Celestial { ... }
final class Comet implements Celestial { ... }
Sealing and record classes
Sealed classes work well with record classes (JEP 395). Record classes are implicitly final.
https://openjdk.org/jeps/397