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 : 

The most powerful advantage of sealed classes appears when combined with switch expressions. Because the compiler knows every possible subclass, it validates whether your code handles all paths at compile-time.
You no longer need to write a redundant, unreachable 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

Popular posts from this blog

CodeCrafters Pauses New Challenges: A Difficult Moment for One of the Best Developer Learning Platforms

YouTube's New AI Labels, Spotify's AI Podcasts, and Apple's Next Audio Mystery Signal a Changing Tech Landscape

How a Former Meta Engineer Tackles an AI Coding Interview in Real Time