Java 14 records canonical constructor

Brian Goetz brian.goetz at oracle.com
Thu Jun 4 18:01:58 UTC 2020


tl;dr: you're right, and we've already fixed it for an upcoming preview.

By way of explanation about how this came about ... it took us a little 
bit of time to come to the current formulation of "compact constructor", 
and the thinking about auto-committing fields predates the current 
formulation.  So the behavior you are seeing has its roots as "more 
lenient constructors", rather than encouraging a different construction 
mode.  It took a while for the details to catch up with the programming 
model on this one.  Surely the intent was as you say -- the constructor 
should only contain stuff that can't be derived from the record 
declaration, which means it will often be empty.

The model we have now is: the constructor arguments show up as set by 
the caller, but are mutable -- if you want to normalize them, do so by 
mutating them, and then they all get committed to the fields at once.  
The benefit here is that there are fewer weird orderings that the user 
has to reason about.

This is a great example of why we do preview releases -- since its hard 
to imagine all of these up front.

On 6/4/2020 1:53 PM, Christian Beikov wrote:
> Hello,
>
> I recently found out that a record constructor can set the record 
> components explicitly and was kind of surprised. I thought that a 
> record is a plain data carrier and that I can re-construct a record 
> object from it's components, but this is not guaranteed.
>
> Here a quick example:
>
> public record UserRecord(Integer id, String userName) {
>     public UserRecord {
>         if (Character.isUpperCase(userName.charAt(0))) {
>             this.userName = null;
>         } else {
>             this.userName = userName.toUpperCase();
>         }
>     }
> }
>
> IMO setting a field/record component directly should be prohibited. A 
> developer should move such a logic to a static method or a different 
> constructor. The canonical record constructor should only do sanity 
> checks i.e. argument is not-null, not blank etc. but not alter the 
> arguments or set the fields manually. It's ok for an additional 
> non-canonical constructor to alter the arguments though.
>
> What do you think? Was that an oversight or is this intended? If it is 
> intended, what is the reasoning for allowing this?
>
> I don't have a problem with this behavior. I just wouldn't have 
> expected it. If I remember correctly, there were some talks about 
> de-construction patterns at conferences that pointed out, that being 
> able to re-construct a record from the component state is a vital 
> property of records.
>
> Regards,
>
> Christian
>



More information about the amber-dev mailing list