Skip to content

Java Sealed Classes

What is Sealed Classes?

A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so.

A class is sealed by applying the sealed modifier to its declaration. Then, after any extends and implements clauses, the permits clause specifies the classes that are permitted to extend the sealed class.

The classes specified by permits must be located near the superclass: either in the same module (if the superclass is in a named module) or in the same package (if the superclass is in the unnamed module).

For example,

  • permits class and sealed class are in same module

    Java
    package com.example.geometry;
    
    public abstract sealed class Shape
        permits Circle, Rectangle, Square { ... }
    
  • permits class and sealed class are not in same module

    Java
    package com.example.geometry;
    
    public abstract sealed class Shape
        permits com.example.veda.Circle, com.example.exia.Rectangle, com.example.unicorn.Square { ... }
    

Sealing a class restricts its subclasses. User code can inspect an instance of a sealed class with an if-else chain of instanceof tests, one test per subclass; no catch-all else clause is needed. For example, the following code looks for the three permitted subclasses of Shape:

Shape rotate(Shape shape, double angle) { if (shape instanceof Circle) return shape; else if (shape instanceof Rectangle) return shape.rotate(angle); else if (shape instanceof Square) return shape.rotate(angle); // no else needed! }

A sealed class imposes three constraints on its permitted subclasses:

  1. The sealed class and its permitted subclasses must belong to the same module, and, if declared in an unnamed module, to the same package.

  2. Every permitted subclass must directly extend the sealed class.

  3. Every permitted subclass must use a modifier to describe how it propagates the sealing initiated by its superclass:

    • A permitted subclass may be declared final to prevent its part of the class hierarchy from being extended further. (Record classes (JEP 395) are implicitly declared final.)

    • A permitted subclass may be declared sealed to allow its part of the hierarchy to be extended further than envisaged by its sealed superclass, but in a restricted fashion.

    • A permitted subclass may be declared non-sealed so that its part of the hierarchy reverts to being open for extension by unknown subclasses. (A sealed class cannot prevent its permitted subclasses from doing this.)

Sealed interfaces

As for classes, an interface can be sealed by applying the sealed modifier to the interface. After any extends clause to specify superinterfaces, the implementing classes and subinterfaces are specified with a permits clause.

For example,

Java
sealed interface Celestial
    permits Planet, Star, Comet { ... }

final class Planet implements Celestial { ... }
final class Star   implements Celestial { ... }
final class Comet  implements Celestial { ... }

Sealing and record classes

Sealed classes work well with record classes (JEP 395). Record classes are implicitly final.

https://openjdk.org/jeps/397