Loosening requirements for super() invocation

Brian Goetz brian.goetz at oracle.com
Thu Jan 26 16:59:41 UTC 2023


What we're seeing here is something that happens all the time -- we 
start with a notion of "hey, it would be great to improve the language 
in X way", and then, as we start to write down specifics, realize that 
there might be a better design center.

We got here by observing "gee, the VM is much more tolerant than the 
language here, maybe we should align the language to the VM", along with 
some obvious examples of code we can't write today that we'd like to be 
able to write.

As we look at the implications of this, though, we start to see that the 
cost/risk/complexity keeps cropping up in the lower-value aspects.  To 
summarize, here are the things you originally proposed to align:

  - Allowing statements before the this/super;
  - Choosing different super/this ctors in different paths;
  - Initializing fields prior to this being DA.

I think we can agree that the first bullet subsumes most of the pain 
that users are in; it addresses things like "putting logic where it 
belongs", allowing the same computed value to be used multiple times 
without recomputing it, etc.  The second feels fairly niche, and while I 
can certainly imagine occasionally wanting it, is probably 100x less 
common than the first, and is where the vast majority of new spec 
complexity would come from. The third seems a workaround for classes 
that are already kind of broken with respect to this-escape, and I'm not 
sure we win by encouraging this (since there's still an escaping `this`.)

So it feels to me that the emerging consolidated design center is 
"statements before this/super".  The spec impact is quite small and 
compact, and the expressiveness impact is pretty significant.  I think 
rallying around this consolidated center will result in a better chance 
of success, and a stronger payoff.





On 1/26/2023 11:12 AM, Archie Cobbs wrote:
> Hi Maurizio,
>
> Thanks very much for taking time to review.
>
> On Thu, Jan 26, 2023 at 8:55 AM Maurizio Cimadamore 
> <maurizio.cimadamore at oracle.com> wrote:
>
>     One example that I didn't get was the NullPointer vs. IAE - to me
>     this seems another case where you want to validate the parameter
>     before passing it to the superclass constructor - e.g. the same as
>     the very first example. For this reason, this example seems weak
>     to me - and the JEP would probably be better off with it omitted
>     (unless I missed some more subtle point, which is possible).
>
>
> Yes... I also thought maybe we should combine those two examples into 
> one. You've confirmed the hunch so I'll make that change.
>
>     what if the class initialized a protected field in the superclass
>     before the superclass constructor is called?
>
>
> That possibility may seem "weird" because it's a new possibility for 
> the first time in 25+ years, but I'd argue that with a little analysis 
> it turns out it doesn't actually lead to any problematic or surprising 
> outcome.
>
> One could also argue that the language already allows much weirder 
> things, like 'this' escapes where a subclass can observe a supposedly 
> final field with the wrong value...
>
> Anyway, here's a breakdown of what happens if a subclass writes to a 
> superclass field prior to super():
>
> If the superclass field is final, assignment is not allowed - you get 
> the usual "cannot assign a value to final variable x" (no change here).
>
> Otherwise, before super() is invoked, the field may not be read, and 
> invocation of superclass methods are disallowed, so the field's value 
> can have no effect on anything.
>
> When super() is invoked, either the superclass constructor overwrites 
> the value or it doesn't (if it reads the value, then presumably that's 
> intentional).
>
> If the superclass constructor overwrites the value, the field gets its 
> new value, as expected.
>
> If the superclass constructor doesn't overwrite the value, the field 
> retains the value written by the subclass, as expected.
>
> So in a nutshell, it behaves as one would expect: either the 
> superclass constructor overwrites the value, or it doesn't. Life goes on.
>
> (And if you don't like subclass constructors writing to your fields 
> prior to super(), you can make them private or final, or just 
> overwrite them in your constructor.)
>
> So yes this scenario is new and different, but I don't think it's fair 
> to say it's problematic. It's just new.
>
>     My feeling is that it would be better to start simple(r), and, at
>     least for the time being, not to give instance field initializers
>     any special treatment.
>
>
> Certainly agree it would be simpler... but it would be at the cost of 
> eliminating the only tool we'll likely ever have for dealing with a 
> superclass 'this' escape, which is one of the primary motivations 
> behind this change.
>
> But back to the crux... if what you're saying is that you're worried 
> about the uncertainty around initializing fields prior to super(), 
> does the earlier breakdown showing that it's harmless (so to speak) 
> help any?
>
> Thanks,
> -Archie
> -- 
> Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230126/edb87aec/attachment-0001.htm>


More information about the amber-dev mailing list