IdentityObject & abstract superclasses
Brian Goetz
brian.goetz at oracle.com
Thu Sep 3 14:37:09 UTC 2020
The "lacks a no-arg ctor" is new and interesting. I think what you're
saying is that having an explicit no-arg ctor with an empty body is a
more stable signal of intent than an implicit one? I can see that.
Shouldn't the non-empty body one be "declares any constructor with a
non-empty body", regardless of arity? The only reasonable thing here
would be a side-effect (like an instance initializer) or a nontrivial
super call, both of which seem to put you in the Identity category.
Still not sold on keying off the existence of a constructor with a novel
shape at the classfile level. Seems too clever, and comes with a
complex verification.
On 9/2/2020 7:30 PM, Dan Smith wrote:
> Summarizing, here's what I think we want:
>
> ---
> Language features
>
> java.lang.IdentityObject is a normal interface, can be implemented/extended by any class or interface.
>
> A non-inline class with any of the following properties implicitly implements IdentityObject:
> - Is concrete (java.lang.Object excluded)
> - Declares a (possibly private) instance field
> - Is an inner class with an enclosing instance
> - Declares an instance initializer
> - Lacks a no-arg constructor (explicit or implicit)
> - Declares a no-arg constructor with a non-empty body (something other than 'super();')
> - Declares a synchronized method
>
> A warning encourages classes in the last four categories to explicitly implement IdentityObject in order to ensure stable class evolution. (Possibly of the "this will become an error in a future release" variety.)
>
> (Note that I'm tentatively allowing constructor overloading in a non-IdentityObject class. It's not generally useful, but is harmless and could be useful in some special circumstances.)
>
> It is a compile-time error if (among other things) an inline class:
> - Implements IdentityObject, directly or indirectly
> - Can't access its superclass's no-arg constructor
> - Declares a synchronized method
>
> ---
> JVM features
>
> Traditionally, a class declares that it supports identity subclasses by declaring one or more <init> methods. (Because with no <init> method, it's impossible to initialize a subclass instance.)
>
> Similarly, a class declares that it supports inline subclasses by declaring an <init> method whose ACC_ABSTRACT flag is set. Invocations of that method are no-ops. (Tentatively. We could encode this differently. The important metadata is i) the class supports inline subclasses, and ii) access flags for inline subclasses.)
>
> A class that is not inline and does not declare support for inline subclasses implicitly implements IdentityObject.
>
> A class that declares support for inline subclasses is subject to the following constraints at class load time:
> - Must be ACC_ABSTRACT (java.lang.Object excluded)
> - Must not declare an instance field
> - Must not declare a synchronized method
> - Must not implement IdentityObject, directly or indirectly
> - Must have access to extend the superclass (per the super's abstract <init> method)
>
> An inline class is subject to similar constraints at class load time:
> - Must not be ACC_ABSTRACT and must be ACC_FINAL
> - All fields must be ACC_FINAL
> - Must not declare a synchronized method
> - Must not implement IdentityObject, directly or indirectly
> - Must have access to extend the superclass (per the super's abstract <init> method)
>
> ---
> API features
>
> (Optionally) The method Class.Interfaces(), and similar reflection API points, filters out IdentityObject when it is not explicitly named in the class file.
>
More information about the valhalla-spec-experts
mailing list