Sealed classes and interfaces
Introduced as a preview in Java 15 and officially released in Java 17, Sealed classes and interfaces act as a middle ground between an open hierarchy and a fully locked-down final class. They restrict which other classes or interfaces may extend or implement them, giving developers the possibility to choose their domain models and class hierarchies.
Syntax:
To create a sealed hierarchy, you use the sealed keyword combined with the permits clause to specify the allowed subclasses.
public sealed class shape permits Circle, Square, Rectangle{}
Every permitted subclass must explicitly choose how it handles its own inheritance using one of three specific modifiers:
final: closes the chain entirely, which means this subclass cannot be extended further.
sealed: continues a restricted chain; it must specify its own permitted subclasses.
non-sealed: reopens the chain; any arbitrary class can now extend this subclass.
Important Constraints:
Location Boundaries: Permitted subclasses must reside in the same package(if using the unnamed module) or the same named module as the sealed.
Direct Extension: Permitted subclasses must directly extend or implement the sealed type.
Implicit Permits: If you define the sealed class and its subclasses in the same source file, you can omit the permits clause. The compiler automatically infers the allowed classes.
Records Compatibility: Java records can implement sealed interfaces. Because records are implicitly final, they do not require an additional modifier.
Key Benefit: Exhaustive Pattern Matching :
switch expressions. Because the compiler knows every possible subclass, it validates whether your code handles all paths at compile-time.default block. If a developer adds a new Triangle subclass later, the compiler will instantly throw an error across all your switch logic until it is safely handled.public double getArea(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Square s -> s.side() * s.side();
case Rectangle r -> r.length() * r.width();
// No 'default' block required!
};
}
Comments
Post a Comment