Java Sealed Classes is a new feature introduced in Java 17 that enhances type safety and readability in certain programming scenarios. Let's dive into understanding what sealed classes are, their benefits, and how to use them.
Sealed classes are a restricted form of an abstract class in Java that allows you to control which classes can extend it. This feature is designed to improve type safety, maintainability, and readability in certain scenarios like Enum-like classes and Strategy pattern implementations.
To create a sealed class, you need to use the sealed keyword followed by the access modifier (public, protected, or default), and then provide a list of permitted subclasses inside a permits clause. Here's an example of a sealed class called Shape:
public sealed class Shape permits Circle, Rectangle {
// Class definition and methods
}In the example above, only Circle and Rectangle can extend Shape. Any other attempt to extend Shape will result in a compile-time error.
If you want to allow additional classes to extend a sealed class in the future, you can use the non-sealed keyword. This keyword allows new classes to extend the sealed class without modifying the original sealed class definition. Here's an example:
public sealed class Shape permits Circle, Rectangle {
// Class definition and methods
}
public final class Triangle extends Shape {
// Triangle class definition and methods
}
public sealed class Shape permits Circle, Rectangle, Triangle {
// This sealed class definition now allows Triangle to extend Shape
}In the example above, we first define a sealed class Shape with Circle and Rectangle as permitted subclasses. Later, we create a Triangle class that extends Shape, but the compiler throws an error as Triangle is not a permitted subclass. To fix this, we modify the Shape class to include Triangle in the permitted subclasses list.
Let's consider a use case of a Strategy pattern where we have several algorithms for calculating the area of various shapes. We can create a sealed class ShapeStrategy to represent the algorithms and enforce type safety:
public sealed class ShapeStrategy permits CircleStrategy, RectangleStrategy {
public abstract double calculateArea(Shape shape);
}
public final class CircleStrategy extends ShapeStrategy {
@Override
public double calculateArea(Shape shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.getRadius() * circle.getRadius();
}
throw new IllegalArgumentException("Invalid Shape");
}
}
public final class RectangleStrategy extends ShapeStrategy {
@Override
public double calculateArea(Shape shape) {
if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
return rectangle.getWidth() * rectangle.getHeight();
}
throw new IllegalArgumentException("Invalid Shape");
}
}In the example above, we create a sealed class ShapeStrategy with CircleStrategy and RectangleStrategy as permitted subclasses. Each strategy calculates the area of a specific shape (Circle or Rectangle) and throws an exception for invalid shapes.
What is the purpose of the `sealed` keyword in Java?