What is the difference between a final and a non-sealed class in Java 15's sealed-classes feature?

Viewed 1190

I have the following sealed interface (Java 15):

public sealed interface Animal permits Cat, Duck {

    String makeSound();
}

This interface is implemented by 2 classes:

public final class Cat implements Animal {

    @Override
    public String makeSound() {
        return "miau";
    }
}

public non-sealed class Duck implements Animal {

    @Override
    public String makeSound() {
        return "quack";
    }
}

Can someone tell me the difference between final and non-sealed? final stops me from creating other sub-classes but what behavior does non-sealed apply to Duck?

2 Answers
  • As you've marked Cat as final, no other class can extend Cat.
  • As you've marked Duck as non-sealed, any class can extend Duck.

When marking a class as sealed, all directly extending classes (the ones after the permits clause) have to be marked either as final, sealed or non-sealed:

  • Marking a class that extends a sealed class as sealed, applies the same effect on it: Only classes specified after the permits clause are allowed to extend it.

  • non-sealed just "breaks the seal", so the effect doesn't have to be carried on down the hierarchy. The extending class is open (again) for being extended by unknown subclasses itself.

  • final is effectively the same as sealed without any class specified after the permits clause. Notice that specifying nothing after permits is not possible, so sealed cannot replace final.

A final class has zero subclasses, meaning no other class can extend it. Any class can extend the non-sealed class.

When you mark a class as sealed, only the permitted subclasses can extend it and can have only these modifiers final, sealed, or non-sealed:

public sealed class NumberSystem
    // The permits clause has been omitted
    // as all the subclasses exists in the same file.
{ }
non-sealed class Decimal extends NumberSystem { .. }
final class NonRecurringDecimal extends Decimal {..}
final class RecurringDecimal extends Decimal {..}

Though, the NumberSystem root level hierarchy is closed to set of known classes, you can allow the sub hierarchies to be open by using the non-sealed keyword.

The sealed and non-sealed combination allows you to restrict parts of your hierarchy but not all.

In the below diagram, we restricted the root hierarchy of the sealed class NumberSystem to a known set of subclasses. However, the non-sealed Decimal class allows any unknown subclass such as RecurringDecimal to extend it.

Related