Java sealed classes and interfaces, introduced in Java 15 and officially supported in Java 17, provide developers with a mechanism to control which classes or interfaces can extend or implement them. By using the sealed
keyword, you can explicitly define the set of permitted subclasses or implementers, ensuring tighter control over your class hierarchy. This feature is handy in scenarios where you need to work with a fixed set of related types — like specific shapes in a geometric application or types of vehicles in a transportation system. In such cases, you can prevent new types from being introduced beyond those initially specified, maintaining consistency and preventing potential errors in your codebase. Additionally, sealed classes and interfaces improve security, maintainability, and readability by making the code’s intent explicit. Leveraging Java development services, you can effectively implement these features to enhance your applications. Let us delve deeper to understand Sealed Classes and Sealed Interfaces in Java.
1. Sealed Classes
- The concept of sealed classes in Java was introduced in Java 15 as a preview feature and became a standard feature in Java 17.
- Sealed classes provide a way to restrict or limit the number of classes that can inherit the given class, thereby offering fine-grained control over the inheritance hierarchy.
- A sealed class can be inherited only by the classes that are allowed or permitted to access them, ensuring that the class hierarchy remains controlled and predictable.
- The feature introduces three new modifiers:
sealed
,non-sealed
, andpermits
, which help in clearly defining the inheritance structure.
In practical scenarios, sealed classes are particularly useful in domain-driven design, where a developer might want to model a domain with a limited set of variations. For instance, consider a financial application where different types of bank accounts (Savings, Checking, etc.) need to be defined. By using a sealed class, you can ensure that only these predefined account types exist, preventing the accidental introduction of invalid or unsupported account types.
2. Sealed Interfaces
Sealed interfaces extend the concept of sealed classes to interfaces, allowing developers to restrict the set of classes that can implement an interface. To seal an interface, apply the modifier sealed
in its declaration, and use the permits
clause to list the classes allowed to implement the sealed interface. This control is especially useful in cases where you want to limit the implementations of an interface to a known set of classes, making the code more predictable and easier to maintain.
2.1 Example 1
public sealed class Coaching permits Vaibhav, Anjali { public void info() { system.out.println(x: "Coaching Class") } } public non - sealed class Anjali extends Coaching { public void info() { System.out.println(x: "hi friends i am Anjali") } } public non - sealed class Vaibhav extends Coaching { public void info() { System.out.println(x: "hi friends i am Vaibhav") } } class main { public static void main(string args[]) { Human h1 = new Vaibhav(); Human h2 = new Anjali(); h1.info(); h2.info(); } }
In this example, the Coaching
class is sealed, meaning only the classes Vaibhav
and Anjali
are allowed to extend it. This ensures that no other classes outside those specified can inherit from Coaching
, providing a controlled and well-defined hierarchy.
2.2 Example 2
public sealed class Colors permits Red, Blue, Green { // class body } public final class Red extends Colors { // class body } public sealed class Blue extends Colors permits FilledBlue { // class body } public non - sealed class Green extends Colors { // class body } public final class FilledBlue extends Blue { // class body }
This example demonstrates a more complex inheritance hierarchy using sealed classes, where Colors
is a sealed class with three permitted subclasses: Red
, Blue
, and Green
. The Red
class is final, meaning it cannot be further subclassed. The Blue
class is sealed and permits only FilledBlue
to extend it, while Green
is non-sealed, allowing unrestricted subclassing.
2.3 Key Points
- Sealed classes and interfaces provide explicit control over the inheritance hierarchy by clearly listing the classes that can extend or implement them.
- Final classes within this hierarchy act as endpoints in the inheritance chain, preventing further subclassing and ensuring that the hierarchy remains stable and well-defined.
- Non-sealed classes offer flexibility within a controlled hierarchy by allowing unrestricted subclassing beyond the permitted set, effectively ending the controlled hierarchy at that point.
- This structure allows developers to define a very controlled and predictable inheritance structure while still offering flexibility where needed, which is particularly beneficial in large-scale enterprise applications where maintaining consistency and preventing bugs is critical.
2.4 Limitations
- Subclasses that are permitted must belong to the same module as the sealed class or interface, ensuring that the class hierarchy is controlled within a single module.
- The permitted subclasses must explicitly extend the sealed class or implement the sealed interface, providing clear visibility and control over the inheritance structure.
- Modifiers like
final
,sealed
, andnon-sealed
must be defined in every permitted subclass or implementation, which may require careful design and planning to ensure consistency and maintainability. - Skilled developers can ensure that sealed classes and interfaces are used to enhance your application’s architecture without creating unnecessary complications.
2.5 Comparison between Sealed Classes and Interfaces
Sealed Classes | Sealed Interfaces |
---|---|
Sealed classes restrict subclasses, and only classes that are explicitly permitted can extend a sealed class, which must belong to the same module as the sealed class. | Sealed interfaces restrict implementation to a predefined set of classes, offering control over the types that can implement the interface, ensuring a stable and predictable type hierarchy. |
We typically use sealed classes when we want to define a closed set showcasing some kind of hierarchy, such as in a financial or geometric domain, where only a fixed set of types is valid. | Sealed interfaces are useful in complex systems where multiple inheritance and type hierarchies are used, such as in event-driven architectures or frameworks where the behavior of certain components needs to be restricted. |
Sealed classes enforce a strict hierarchy where all subclasses must be known at compile-time, providing compile-time safety and reducing the risk of runtime errors. | Sealed interfaces allow for a more flexible design, enabling complex type hierarchies while still maintaining control over the types that can implement the interface, ensuring consistent behavior across implementations. |
4. Conclusion
In conclusion, sealed classes and interfaces in Java offer powerful tools for controlling and restricting inheritance and implementation hierarchies. While they share the common goal of providing control and safety, they do so in different contexts and with different levels of flexibility. Sealed classes are best suited for scenarios where a closed, well-defined type hierarchy is needed, while sealed interfaces excel in complex systems where multiple inheritance and type hierarchies are used. Both features, when used appropriately, can greatly enhance the maintainability, security, and readability of your codebase, making them valuable additions to the Java language.
Learn how Java 23 compares to Java 22, from performance upgrades to new language features.