Field initialization before 'super'
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Dec 13 21:07:20 UTC 2023
> From: "Archie Cobbs" <archie.cobbs at gmail.com>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "daniel smith" <daniel.smith at oracle.com>, "amber-spec-experts"
> <amber-spec-experts at openjdk.java.net>
> Sent: Wednesday, December 13, 2023 5:29:27 PM
> Subject: Re: Field initialization before 'super'
> On Wed, Dec 13, 2023 at 10:02 AM Remi Forax < [ mailto:forax at univ-mlv.fr |
> forax at univ-mlv.fr ] > wrote:
>> > No such restriction is needed for non-final fields; but it's an open question
>> > whether we should prohibit all writes before 'this()' anyway.
>> I would say, keep that restriction.
> I tend to agree. One benefit would be it creates more separation between final
> fields and non-final fields, which would help encourage people to make fields
> final so they get all the benefits.
>> > Writes to non-final fields with initializers are disallowed, to avoid confusion
>> > about sequencing (the field initializer will always run later, overwriting
>> > whatever you put in the constructor prologue.)
>> This seems to suggest that final fields with initializer should be written
>> before the call to super() by default even if it's not a backward compatible
>> change.
> That could only work if the initializer doesn't read "this"... which means only
> some initializers would qualify, which would be confusing.
yes,
>> captured fields in lambda are like strict but captured fields is inner classes
>> are like normal fields.
> I was curious why this would be true and it appears it's not true, at least from
> this test:
> $ cat Test.java
> public class Test {
> public Test(String x) {
> new Runnable() {
> @Override
> public void run() {
> System.out.println(x);
> }
> }.run();
> }
> }
> $ javap -c -classpath classes Test\$1
> Compiled from "Test.java"
> class Test$1 implements java.lang.Runnable {
> final java.lang.String val$x;
> Test$1();
> Code:
> 0: aload_0
> 1: aload_2
> 2: putfield #1 // Field val$x:Ljava/lang/String;
> 5: aload_0
> 6: invokespecial #7 // Method java/lang/Object."<init>":()V
> 9: return
> ...
> You can see in the Test$1 constructor Test$1.x is being initialized prior to
> super().
Yes, but you can still change the value of the field by reflection, unlike with the fields of a lambda proxy, so the field containing the captured value is not strict.
>> > - Can I have my implicit 'super()' call go at the end of my constructor?
> My opinion is also "no" on this question... but because it would add another
> logical fork in developers' minds for too little benefit. It's easy enough to
> just put it in there explicitly.
What we are trying to do here, is to follow Dan's idea that there is no need for an additional keyword and that the compiler can infer the strictness by itself.
As you said, the problem of that idea is that the developer is not really in control, subtle changes like the initializer depending on 'this' make the final field strict or not.
> -Archie
regards,
Rémi
> --
> Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20231213/2642e48c/attachment-0001.htm>
More information about the amber-spec-experts
mailing list