Making a class sealed means that the compiler knows the complete list of implementation classes at compile time. Therefore, it can confirm that (for example) every possible match has been handled.
Consider it similar to checked exceptions: At compile time, the compiler ensures that every checked exception that could be thrown is handled somehow (either by catching or by a throws clause), so it's guaranteed that the flow control will be formally consistent.
Java 17 Features: Pattern Matching for switch and Sealed Classes
class - What are sealed classes in Java 17? - Stack Overflow
Sealed class in Java
JEP 441: Pattern Matching for switch. Formally Proposed to Target JDK 21
You can follow this link for examples.
In short, sealed classes gives you the control of which models, classes etc. that can implement or extend that class/interface.
Example from the link:
public sealed interface Service permits Car, Truck {
int getMaxServiceIntervalInMonths();
default int getMaxDistanceBetweenServicesInKilometers() {
return 100000;
}
}
This interface only permits Car and Truck to implement it.
The JEP 409 explains it as
A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so.
A more practical explanation is the following:
The situation in the past was:
- You could not restrict an interface being extended by another interface
- You could not constraint which classes where able to implement a specific interface.
- You had to declare a class as final in order to not be extended by another class. This way no class could extend the declared final class. This was black or white approach.
The current situation with sealed keyword is:
You can now restrict an interface being extended by other interfaces and make a rule for only some specific interfaces which will be allowed to extend it.
Example:
public sealed interface MotherInterface permits ChildInterfacePermitted {} //Has to be declared either as sealed or non-sealed public non-sealed interface ChildInterfacePermitted extends MotherInterface {} public interface AnotherChildInterface extends MotherInterface {} //compiler error! It is not included in the permits of mother intefaceYou can now create an interface and select only specific classes that are allowed to implement that interface. All other classes are not allowed to implement it.
Example:
public sealed interface MotherInterface permits ImplementationClass1 {} //Has to be declared either as final or as sealed or as non-sealed public final class ImplementationClass1 implements MotherInterface {} public class ImplementationClass2 implements MotherInterface {} //compiler error! It is not included in the permits of mother intefaceYou can now restrict a class being extended (same as before with final) but you can now allow some specific classes to extend it. So now you have more control as before the keyword final was absolute restricting every class from extending the declared final class
Example:
public sealed class MotherClass permits ChildClass1 {} //Has to be declared either as final or as sealed or as non-sealed public non-sealed class ChildClass1 extends MotherClass {} public class ChildClass2 extends MotherClass {} //compiler error! It is not included in the permits of MotherClass
Important notes:
The sealed class and its permitted subclasses must belong to the same module, and, if declared in an unnamed module, to the same package.
Example:
Let's say that we have the same unnamed module and the following packages
-packageA -Implementationclass1.java -packageB -MotherClass.javaor
-root -MotherClass.java -packageA -Implementationclass1.javaYou will get the error Class is not allowed to extend sealed class from another package. So if you have an unnamed module all participating classes and interfaces for the sealed function must be placed exactly on the same package.
Every permitted subclass must directly extend the sealed class.