Java 16 Sealed Classes (JEP 360)

Java 16 introduced sealed classes, which are a new kind of class that allows you to specify which other classes or interfaces can subclass or implement them. Sealed classes are a useful way to control the inheritance hierarchy of your classes and to prevent unintended subclassing or implementation.

Here is an example of how to define a sealed class in Java:

sealed class Shape permits Circle, Rectangle {
  abstract double area();
}

final class Circle extends Shape {
  private final double radius;
  Circle(double radius) { this.radius = radius; }
  double area() { return Math.PI * radius * radius; }
}

final class Rectangle extends Shape {
  private final double width;
  private final double height;
  Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }
  double area() { return width * height; }
}

In this example, we are defining a sealed class called Shape that represents a geometric shape. The Shape class is sealed using the sealed keyword, and it is permitted to be subclassed by the Circle and Rectangle classes using the permits clause. The Circle and Rectangle classes are defined as final, which means that they cannot be subclassed further.

To use the sealed class and its subclasses, we can write code like this:

Shape s = new Circle(1.0);
System.out.println(s.area());  // 3.141592653589793

Sealed classes can be used in a variety of contexts, such as in method parameters and return types, field declarations, and local variables. They can also be used to enforce type safety and to prevent unintended polymorphism.

One important thing to note about sealed classes is that they are not suitable for all cases. In particular, they may not be suitable for cases where you need to define a large number of subclasses or where you need to allow subclassing by arbitrary classes. In these cases, it may be more appropriate to use regular classes or interfaces instead.