Sealed Class vs Final Class in Java

In the world of Java programming, understanding the between different class types is crucial for designing robust and maintainable applications. Two important concepts in this regard are Sealed Classes and Final Classes. Although they might appear similar at first glance, they serve distinct purposes and have unique characteristics. This post will dive into the differences between Java Sealed Classes and Final Classes, offering insights into their functionalities and use cases. 

What is a Final Class? 

A final class in Java is a class that cannot be extended. In other words, you cannot create a subclass of a final class. This is often done to ensure immutability or to maintain the integrity of the class logic.

Example of a Final Class

public final class Constants {
    public static final String APP_NAME = "MyApp";
    // Other constants...
}

In this example, Constants is a final class containing application-wide constants. Marking it as final ensures that no other class can extend it, thereby preserving the intended use as a constants-only class.

What is a Sealed Class? 

Sealed classes, introduced in Java 15 as a preview feature and finalized in Java 17, are classes that allow you to control which other classes can extend them. This is more flexible than final classes, as it lets you define a restricted set of subclasses. 

Example of a Sealed Class

// Sealed class example
sealed abstract class Shape permits Circle, Square {
    abstract double area();
}

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

non-sealed class Square extends Shape {
    private final double side;
    Square(double side) { this.side = side; }
    @Override double area() { return side * side; }
}

public class SealedVsFinalClasses {
    public static void main(String[] args) {
        // Using sealed class
        Shape circle = new Circle(5);
        System.out.println("Area of Circle: " + circle.area());
    }
}

Output:

Area of Circle: 78.53981633974483

Explanation:

1. Shape is a sealed class, allowing only certain classes (Circle, Square) to extend it. This ensures control over the inheritance hierarchy.

2. Circle and Square are subclasses of Shape, but Circle is final, meaning no further subclassing is possible.

3. In SealedVsFinalClasses, instances of both a sealed subclass (Circle) and a final class (ImmutablePoint) are created and used.

5. The output demonstrates the functionality of both: circle.area() computes the area.

Key Differences 

1. Extensibility 

Final Class: Cannot be extended by any other class. 

Sealed Class: Can be extended by a specific set of classes. 

2. Use Cases 

Final Class: Used when you want to prevent any modification or extension of a class, often for reasons of security, immutability, or design simplicity. 

Sealed Class: Ideal for situations where you need a closed set of types, such as when implementing a domain model or a finite set of operations in a system. 

3. Flexibility 

Final Class: Offers a rigid structure with no flexibility in terms of class hierarchy. 

Sealed Class: Provides more flexibility, allowing the creation of a controlled and predictable hierarchy. 

4. Design Intent 

Final Class: Indicates that the class is complete in its current form and should not be altered or extended. 

Sealed Class: Suggests a more comprehensive design consideration, where the class is intended to be extended in controlled and predefined ways.

Conclusion

- A sealed class is a class that can only be extended by a specific set of classes or interfaces, providing a more controlled form of inheritance.

- A final class is a class that cannot be extended at all, ensuring its implementation remains unchanged by subclasses.

Comments