Understanding Sealed Classes in Java 17

What are Sealed Classes?

Sealed classes allow you to control which classes can extend (inherit from) a certain class. Think of it as a way to create a list of approved subclasses.

Why Use Sealed Classes?

Before Java 17, there was no built-in way to restrict which classes could inherit from another class. This could lead to confusion and unexpected behavior in your code. Sealed classes make this restriction clear and enforceable.

How Sealed Classes Work

  1. sealed Keyword: You declare a class as sealed using the sealed keyword.
  2. Permits Clause: You specify which classes are allowed to extend your sealed class using the permits clause.
  3. Subclass Types: The allowed subclasses can be:
    • Final: These classes cannot be subclassed further.
    • Non-Sealed: These classes can be extended by other classes.

Simple Example

Let’s use a simple analogy to explain this. Imagine you have a Shape and you only want certain shapes (like Circle and Square) to be recognized as valid shapes.

Code Example


// This is the sealed class
public abstract sealed class Shape permits Circle, Square {
    public abstract double area(); // Abstract method to calculate area
}

// This class can be created but cannot be extended further
public final class Circle extends Shape {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius; // Area of circle
    }
}

// This class can also be created but cannot be extended further
public final class Square extends Shape {
    private final double side;

    public Square(double side) {
        this.side = side;
    }

    @Override
    public double area() {
        return side * side; // Area of square
    }
}

// This class can be extended further
public non-sealed class Triangle extends Shape {
    private final double base;
    private final double height;

    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }

    @Override
    public double area() {
        return 0.5 * base * height; // Area of triangle
    }
}
    

What This Code Does

  1. Shape Class: This is a sealed class. It can only be extended by Circle, Square, or Triangle.
  2. Circle and Square: These are marked as final, meaning no one can create a class that extends them.
  3. Triangle: This is marked as non-sealed, so other classes can still extend it if needed.

Benefits of Sealed Classes

  1. Clarity: It’s clear which classes can inherit from Shape.
  2. Control: You can decide which subclasses are allowed and how they can be used.

Summary

Before Java 17: No clear way to control inheritance; could lead to confusion.
After Java 17: Sealed classes give you clear control over which classes can extend others, making your code easier to understand and maintain.