Refinements for sealed types

Brian Goetz brian.goetz at
Tue Aug 20 19:40:56 UTC 2019

Gathering the various threads in this discussion, here’s what seems a sensible landing place:

1.  A sealed _class_ with no permitted subtypes is a final class.  The distinction between declared-sealed-with-no-permits and declared-final is erased away.  [*]

2.  Sealed abstract classes and interfaces with no permitted subtypes are illegal. 

3.  If a sealed type does not specify a permits list, it can be inferred by enumerating the subtypes in the same compilation unit.  

4.  If a concrete class is a subtype of a sealed type declared in the same compilation unit, and none of the modifiers { sealed, non-sealed, final } are present, it is inferred to be sealed with an inferred permits list (which, according to (1), may be treated as final if there are none.)

5.  (optional) It is an error to specify an explicit permits list if `sealed` is not specified.  

6.  Otherwise, a subtype of a sealed type must have exactly one of the following modifiers: sealed, non-sealed, final.  

 - No need to support ACC_FINAL in conjunction with ABSTRACT or INTERFACE.  
 - Inference of both sealed and permits clauses are purely local — there is no action-at-a-distance (for distances greater than one compilation unit.)  
 - Sealed-ness for subtypes of sealed classes declared separately must be explicit.
 - Co-declared hierarchies get significant ceremony reduction.

[*] This forecloses on directly having “dynamic subtypes” of sealed types, in the same way we can have dynamic nest mates via Lookup.defineClass(). However, there are reasonable workarounds for this should it become desirable.

> On Aug 19, 2019, at 6:58 PM, Brian Goetz <brian.goetz at> wrote:
> I was suggesting that a class:
>     sealed class X { }
> with no permitted subtypes would be _both_ ACC_FINAL *and* have an empty sealing attribute.  The rationale would be:
>  - Reflects intuition that sealed-with-no-permitted-subtypes really means final, but
>  - Allows reflection to distinguish between the two.
> Maybe the reflection behavior isn't important, at which point we just drop the latter.
> On 8/19/2019 6:52 PM, Alex Buckley wrote:
>> On 8/19/2019 3:22 PM, Brian Goetz wrote:
>>> I don't have a strong opinion on whether "sealed but no permitted subtypes" is a habitable space separate from "final", but I'm fine to
>>> say "that means final" for most purposes.  Not sure what reflection
>>> should say; is it OK for a type that is clearly sealed in its declaration to report back as "not sealed, but final?"  Or does
>>> that mean it is both sealed _and_ final (an empty PermittedSubtypes attribute, plus an ACC_FINAL)?
>> Are you referring here to a source declaration such as `sealed interface
>> X {}` where, per Vicente, X.class has ACC_FINAL set? I think X.class.isSealed() should return true and X.class.isFinal() [simplifying for space] should return false. Has there been any discussion of reclaiming ACC_SUPER, 0x0020, for ACC_SEALED in v58 class files? Using an empty attribute to denote sealing is pretty ugly.
>> Alex

More information about the amber-spec-experts mailing list