Loosening requirements for super() invocation
Archie Cobbs
archie.cobbs at gmail.com
Sun Jan 29 22:14:01 UTC 2023
On Fri, Jan 27, 2023 at 2:52 PM Archie Cobbs <archie.cobbs at gmail.com> wrote:
> JEP is updated <https://bugs.openjdk.org/browse/JDK-8300786>. Not
> surprisingly, it has gotten a good bit simpler.
>
FYI, I've added this additional detail:
> (4) Replace the steps for constructor processing in §12.5 with the
> following:
>
> 1. Assign the arguments for the constructor to newly created parameter
> variables for this constructor invocation.
> 2. If this constructor contains an explicit constructor invocation
> (§8.8.7.1), then execute the preceding BlockStatements, if any.
> 3. If this constructor contains an explicit constructor invocation
> (§8.8.7.1) of another constructor in the same class (using this), then
> evaluate the arguments and process that constructor invocation recursively
> using these same six steps. If that constructor invocation completes
> abruptly, then this procedure completes abruptly for the same reason;
> otherwise, continue with step 6.
> 4. This constructor does not contain an explicit constructor
> invocation of another constructor in the same class (using this). If
> this constructor is for a class other than Object, then this
> constructor contains an explicit or implicit invocation of a superclass
> constructor (using super). Evaluate the arguments and process that
> superclass constructor invocation recursively using these same six steps.
> If that constructor invocation completes abruptly, then this procedure
> completes abruptly for the same reason. Otherwise, continue with step 5.
> 5. Execute the instance initializers and instance variable
> initializers for this class, assigning the values of instance variable
> initializers to the corresponding instance variables, in the left-to-right
> order in which they appear textually in the source code for the class. If
> execution of any of these initializers results in an exception, then no
> further initializers are processed and this procedure completes abruptly
> with that same exception. Otherwise, continue with step 6.
> 6. Execute the rest of the body of this constructor. If that execution
> completes abruptly, then this procedure completes abruptly for the same
> reason. Otherwise, this procedure completes normally.
>
> The new step added is Step #2. Note that this means field initializers
(and initialization blocks) execute after super() returns, which is the
same as before but more interesting now that super() is no longer required
to be first.
Currently, there is an illusion of initializers executing at the
"beginning" of the constructor. But in actuality, they have always actually
executed after super() returns. Changing this wouldn't be backward
compatible, and really there's no other option - they couldn't (for
example) execute at the start of the constructor, because initializers are
allowed to reference 'this' and assume the superclass is initialized.
You can observe the current behavioral nuance if you're willing to e.g.
(ab)use static fields:
$ cat InitOrder1.java
public class InitOrder1 {
public static class Class1 {
public Class1() {
Class2.nextIndex++; // bad form here!
}
}
public static class Class2 extends Class1 {
static int nextIndex = 1;
final int index = nextIndex;
}
public static void main(String[] args) {
System.out.println(new Class2().index);
}
}
$ javac InitOrder1.java && java InitOrder1
2
The changed JLS would open the window a little wider for oddities like
this, to include the "static context" statements in a constructor prior to
invoking super(). You still would have to jump through a static field or
other tricks to observe the nuance though.
Here's such an example:
$ cat InitOrder2.java public class InitOrder2 {
public static class Class1 {
static int nextIndex = 1;
final int index = nextIndex;
public Class1() {
nextIndex++;
super();
}
}
public static void main(String[] args) {
System.out.println(new Class1().index);
}
}
$ javac InitOrder2.java && java InitOrder2
2
I think this falls into that category of things where the JLS has more
detail in it than the corresponding programmer's mental model - and that's
OK (see other discussion around switch patterns, instanceof, and primitive
types). I don't think it's likely for a developer to be doing anything that
would allow their mental model to be violated in this way, but of course it
is possible if they try hard enough.
-Archie
--
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230129/dd063612/attachment-0001.htm>
More information about the amber-dev
mailing list