Sealed classes, introduced in Java 17, allows you to restrict the classes or interfaces that can extend or implement them. By providing greater control over class hierarchies, this improves code maintainability and security. Now, let’s explore the complexity of sealed classes and analyze how they work through the use of examples.
Fundamental Principles
- Sealed Keyword: The
sealed
keyword is used to identify a class or interface as sealed. - Permits Clause: A sealed class or interface must specify the classes or interfaces that are allowed to extend or implement it by using the permits clause.
- Final, Non-Sealed, and Sealed Subclasses:
- ‘
final
‘: The keyword ‘final
‘ can be used to declare a subclass that should not be further extended. - ‘
non-sealed
‘: A subclass can be designated as ‘non-sealed
‘ if it allows for further extension without any limitations. - ‘sealed’: The ‘
sealed
‘ keyword can be used to further restrict the hierarchy of a subclass.
- ‘
Example
Let us explain this concept using an example:
// Sealed superclass
public abstract sealed class Shape permits Circle, Rectangle, Square {
// Common properties and methods for all shapes
public abstract double area();
}
// Permitted subclass 1
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;
}
}
// Permitted subclass 2
public sealed class Rectangle extends Shape permits FilledRectangle {
private final double length;
private final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}
// Further permitted subclass of Rectangle
public final class FilledRectangle extends Rectangle {
private final String fillColor;
public FilledRectangle(double length, double width, String fillColor) {
super(length, width);
this.fillColor = fillColor;
}
public String getFillColor() {
return fillColor;
}
}
// Permitted subclass 3
public non-sealed class Square extends Shape {
private final double side;
public Square(double side) {
this.side = side;
}
@Override
public double area() {
return side * side;
}
}
Explanation
- Sealed Superclass: The
Shape
class is defined as sealed and allows just three classes to inherit from it: ‘Circle
‘, ‘Rectangle
‘, and
‘Square
‘. - Final Subclass: The ‘
Circle
‘ class is declared asfinal
, indicating that it cannot be further extended. - Sealed Subclass: The ‘
Rectangle
‘ class is sealed, meaning it allows one subclass: ‘FilledRectangle
‘. - Additional Sealed Subclass: The ‘
FilledRectangle
‘ class is a subclass of ‘Rectangle
‘ and is defined asfinal
, indicating that it cannot be further extended. - Non-Sealed Subclass: The ‘
Square
‘ class is declared as ‘non-sealed
‘, indicating that it can be further extended by other classes.
FAQs About Sealed Classes in Java 17
1. What are sealed classes in Java 17?
Sealed classes are a feature in Java that allow you to restrict which other classes or interfaces can extend or implement them. This contributes to the maintenance of a class hierarchy and is more controlled and predictable.
2. What is the primary purpose of sealed classes?
The primary purpose of sealed classes is to improve code maintainability and security by providing more control over class hierarchies. They help prevent unauthorized extensions and ensure that only specified classes can extend a particular class.
3. How do you declare a sealed class?
You declare a sealed class using the sealed
keyword, followed by the permits
clause, which specifies the allowed subclasses.
public abstract sealed class Shape permits Circle, Rectangle, Square {
// Class body
}
4. What is the permits
clause?
The permits
clause is used to explicitly list the classes or interfaces that are allowed to extend or implement the sealed class or interface. It ensures that only the specified classes or interfaces can be part of the hierarchy.
5. What are the possible subclasses of a sealed class?
A sealed class can have the following types of subclasses:
- ‘
final
‘ subclasses: These cannot be extended further. - ‘
sealed
‘ subclasses: These can continue to restrict their own subclasses. - ‘
non-sealed
‘ subclasses: These can be extended further without restrictions.
6. Can an interface be sealed?
Yes, an interface can be sealed using the same sealed
keyword and permits
clause.
public sealed interface Shape permits Circle, Rectangle, Square {
double area();
}
7. What happens if a class that extends a sealed class does not fit into the final
, sealed
, or non-sealed
categories?
The compiler will throw an error if a subclass of a sealed class does not specify one of final
, sealed
, or non-sealed
. This ensures that the hierarchy remains controlled and well-defined.
8. Can we use sealed classes and records together?
Absolutely, sealed classes and records can be used together. Permitting subclasses of sealed classes allows for the creation of compact and immutable data carriers known as records.
public abstract sealed class Shape permits Circle, Rectangle, Square {
public abstract double area();
}
public final record Circle(double radius) extends Shape {
@Override
public double area() {
return Math.PI * radius * radius;
}
}
9. What are the benefits of using sealed classes?
The benefits include:
- Improve maintainability by controlling class hierarchies.
- Improved security by preventing unauthorized subclassing.
- Improve domain modeling by ensuring that only the appropriate subclasses are utilized.
10. Can sealed classes have non-public subclasses?
Yes, the subclasses listed in the permits
clause can be non-public. However, they must be in the same module or package as the sealed class.
11. Can a sealed class permit an abstract class as a subclass?
Yes, a sealed class can permit an abstract class as a subclass. This abstract class can then define its own permitted subclasses.
public abstract sealed class Shape permits Circle, Rectangle {
public abstract double area();
}
public abstract sealed class Rectangle extends Shape permits Square, FilledRectangle {
// Class body
}
12. How do sealed classes interact with modules?
Sealed classes can be part of a module system. All permitted subclasses must be in the same module as the sealed class. This guarantees that the limits of modules are maintained and the hierarchy remains regulated.