On Apr 29, 2020, at 10:07 AM, Gavin Bierman <gavin.bier...@oracle.com> wrote: > > Talking it through with Dan, I think the best thing for the JLS is to avoid > issues of `this` etc and simply state: > > It is a compile-time error to assign to the instance fields of the > record class in the body of the compact constructor. > > Thoughts?
That sounds fine to me. There was at least one reason to be more restrictive, and that was to help users avoid accidentally observing non-initialized fields. So I’ve lost track of this bit: What happens if the compact constructor calls a virtual method on this? (Say it doesn’t explicitly mention ’this’.) What are the states of the fields when the virtual method runs before and after variable assignments in the compact constructor? All default? Some default some not? To really rub it in: class RecordFieldChangeExperiment { record R0(int x) { public R0 { observeField(); } void observeField() { System.out.println(x); } } record R1(int x) { public R1 { observeField(); ++x; // could be x = Math.max(x, 0); //WAS: this.x = x+1; // could be this.x = Math.max(x, 0); observeField(); } void observeField() { System.out.println(x); } } record R2(int x) { public R2 { observeField(); ++x; // could be x = Math.max(x, 0); observeField(); ++x; // could be x = Math.min(x, 1000); observeField(); } void observeField() { System.out.println(x); } } public static void main(String... av) { new R0(100).observeField(); // 100 100 NO? // 0 100 YES? new R1(100).observeField(); // 100 101 101 NO? // 0 101 101 NO? // 0 0 101 YES? new R2(100).observeField(); // 100 101 102 102 NO? // 0 0 102 102 NO? // 0 0 0 102 YES? } } I think the principled answer is to specify that fields have their default values until after the primary constructor exits. This will surprise people who expect to read the fields in virtual methods called from the constructor. Having all the fields always in their default values is, at least, predictable. IMO that makes up for the surprise, because it can be learned. The other compromises (especially making fields mutable multiple times) lead to more variable behaviors, ensuring a long train of future surprises. (And do any of these observations apply to non-compact constructors? I suppose the answer is “whatever rules apply to non-record classes also apply to records with non-compact canonical constructors”.) — John