Sealed classes, introduced in Java 15 as a preview feature and made permanent in Java 17, allow developers to control which classes can extend or implement them. This feature is part of Project Amber, which aims to improve developer productivity by enhancing the Java language with small but powerful features.
What are Sealed Classes?
Sealed classes are a new kind of class that restricts which other classes or interfaces can extend or implement them. This is done to provide a more robust and maintainable type hierarchy. When you define a sealed class, you specify a set of permitted subclasses.
Benefits of Sealed Classes
- Controlled Inheritance: By specifying which classes can extend a sealed class, you gain better control over your class hierarchy and ensure that it remains well-defined and easy to maintain.
- Exhaustive Pattern Matching: Sealed classes work well with pattern matching features, allowing the compiler to check that all possible cases are covered.
- Enhanced Readability and Maintainability: Clearly defined inheritance structures improve code readability and maintainability.
Defining a Sealed Class
To define a sealed class, you use the sealed
keyword and specify the permitted subclasses with the permits
clause. Here’s an example:
public sealed class Shape permits Circle, Rectangle, Square { // class body
} public final class Circle extends Shape { // class body
} public final class Rectangle extends Shape { // class body
} public final class Square extends Shape { // class body
}
In this example, Shape
is a sealed class, and only Circle
, Rectangle
, and Square
are permitted to extend it. Each subclass must be final
, sealed
, or non-sealed
.
Using Sealed Classes
Sealed classes can be used to model hierarchical structures where the set of subclasses is known and fixed. This is particularly useful in domain modeling and when working with algebraic data types.
Here is an example of using sealed classes with pattern matching:
public class SealedClassExample { public static void main(String[] args) { Shape shape = new Circle(5); String result = switch (shape) { case Circle c -> "Circle with radius " + c.radius(); case Rectangle r -> "Rectangle with width " + r.width() + " and height " + r.height(); case Square s -> "Square with side " + s.side(); }; System.out.println(result); }
}
In this example, we use a switch
expression to handle different types of Shape
. The compiler can ensure that all possible cases are covered because Shape
is sealed.
Conclusion
Sealed classes are a powerful addition to Java, providing better control over class hierarchies and enhancing code readability and maintainability. By using sealed classes, you can create more robust and well-defined type systems in your Java applications.