A sealed class restricts which other classes can extend it, typically achieved using the permits
clause. However, if a sealed class does not specify any permitted subclasses using the permits
clause, it implicitly allows any class within the same compilation unit to extend it. This can lead to unintended inheritance, where classes that should not have been allowed to extend the sealed class can do so at any time.
Given this potential for unintended inheritance:
- should developers always include a
permits
clause when declaring a sealed class to explicitly control the permitted subclasses? - Are there scenarios where omitting the permits clause might be justified or preferable, or is it generally advisable to specify it?
mohamed mahfouz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2
As you wrote:
A sealed class restricts which other classes can extend it, typically achieved using the permits clause. However, if a sealed class does not specify any permitted subclasses using the permits clause, it implicitly allows any class within the same compilation unit to extend it.
Refer to JLS 8.1.6 where this is specified (go to the end of the chapter).
In Java, the compilation unit is the *.java
file (see JLS 7.3). This means that any “unintended inheritance” is impossible when a sealed class does not provide a permits
clause – at least if you do not provide access to the source code, because you have to add the code for the extending class into the same source file as the sealed one. But even then that inheritance is not unintended.
But yes, all sealed classes and interfaces should provide a permits
clause just to make it explicit which classes are allowed to extend/implement it.
Omitting the permits
clause on a sealed class is just an indication of laziness, there is no scenario where it is advisable, justified or preferable.
It is generally best practice to include a permits clause when declaring a sealed class.
This ensures
- explicit control over the class hierarchy
- prevents unintended inheritance, and
- improves code clarity.
Omitting the permits clause should be a deliberate and well-considered decision, typically only justified in controlled or specific scenarios.
For most use cases, specifying the permits clause is advisable to maintain robust and maintainable code.
1