[sealed] Sealed interface as a utility class?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Oct 18 13:47:32 UTC 2019

Hi Tagir,
I think think that what you are asking for is more along the lines of 
having "final interface" rather than sealed which permits nobody. Right?

I agree that it could be worth re-examining the restriction that 
interfaces cannot be marked as final; I think that restriction comes 
from way back; if interfaces are just there to specify a contract which 
all implementation should adhere to, a final interface is a bit of an 

But after the recent addition to the language, the distinction between 
classes and interfaces has gotten quite thin:

- interfaces can have default implementations
- interfaces can have static methods
- interfaces can have private methods

So, it is conceivable that one might now want to use an interface not to 
specify behavior, but, more simply, to define a bad of associate static 
methods. In such a case, marking the interface as 'final' makes perfect 

So, I think the question here is more whether we're philosophically ok 
with people using the "interface" construct in this fashion; one might 
argue that this is, admittedly, quite far from what language designers 
had in mind for interfaces in the first place; but at the same time, as 
you also noted, this didn't stop developers from using interfaces to 
define bags of constants and then having clients 'implement' them (to 
inherit the constants) which was eventually replaced by the more stable 
import static feature.


On 18/10/2019 10:02, Tagir Valeev wrote:
> Hello!
> A utility class (a class that has only static members) is a ubiquitous
> Java pattern. They are used in JDK, common third-party libraries and
> applications. Usually, it's a final class. Since Java 8 (static
> methods were introduced in the interface) it's possible to convert a
> utility class to an interface. There are a number of advantages:
> - It cannot be instantiated, by interface definition. As a result, you
> don't need to create an ugly constructor like `private MyUtils()
> {throw new UnsupportedOperationException();}`
> - If you care much about code coverage, now you would have very bad
> times trying to cover this constructor (some people do this!). Declare
> it as an interface, and the problem is gone.
> - No need to specify `static final` on the fields -- less visual noise
> - No need to specify `static` on nested classes -- less visual noise
> - You cannot accidentally declare a non-static member: it will be a
> compilation error, and IDE will highlight it immediately suggesting a
> fix. My experience shows that people indeed sometimes mistakenly
> declare a non-static member in a utility class and realize this only
> on the first usage. This is frustrating (why I don't see the
> completion option? I just added this method, I know it's there! Is my
> IDE drunk?) and takes time to fix.
> - You cannot accidentally declare a non-static field or a non-static
> nested class. You simply cannot.
> Unfortunately one may implement such an interface which is not what we
> would like to allow. In fact, such an approach was used in early Java
> versions (until import static was introduced in Java 5) to use
> interfaces that declare only constants (this is a subset of utility
> classes). Now it's considered an anti-pattern to implement such an
> interface [1].
> Having sealed classes we may declare such an interface as a sealed and
> provide no implementations at all, making it effectively final.
> Unfortunately (or not), the latest spec draft [2] explicitly disables
> this (9.1.4):
>> It is a compile-time error if a sealed interface has no permitted subtypes.
> This could be worked around introducing a bogus implementor inside:
> public sealed interface MyUtils {
>    private final class X implements MyUtils {} // just to make a compiler happy
>    // static members follow
> }
> This will undermine the first advantage, as the bogus class should
> again have the throwing constructor. However, you still have less
> visual noise, and you've got protection against an accidental
> non-static member. So we may expect that people will (ab)use this
> pattern.
> The question is: whether should we support this or not? If yes, we
> could lift the restriction on sealed interfaces without permits (which
> essentially allows creating final interfaces). We could go further and
> while allowing such interfaces we may disable any instance or default
> methods inside (as nobody could call them anyway) which would make the
> thing even more robust, and everybody would know that final interface
> is a utility class.
> If we don't support this, probably we should spell this out somewhere.
> If somebody going to write a programmer's guide to sealed classes
> (similar to TextBlocks one [3]), probably it's a good point to
> mention.
> A good alternative would be to invent a special syntax for utility
> classes like `utlity class MyUtils {}`. This adds a few restrictions:
> - All members are implicitly static; static modifier is allowed but
> not necessary
> - All fields are implicitly final, like in interfaces
> - Constructors and instance initializers are disallowed
> - Inheritors and instantiation is disallowed
> - A `utility` modifier could be obtained via reflection
> This would be a nice alternative, and there will be no reason to abuse
> other language features.
> With best regards,
> Tagir Valeev.
> [1] https://en.wikipedia.org/wiki/Constant_interface
> [2] http://cr.openjdk.java.net/~gbierman/jep360/jep360-20190830/specs/sealed-types-jls.html
> [3] https://cr.openjdk.java.net/~jlaskey/Strings/TextBlocksGuide_v9.html

More information about the amber-spec-experts mailing list