Java 14 record Syntax seems alien

Brian Goetz brian.goetz at oracle.com
Wed Apr 15 13:35:47 UTC 2020


> I’m sending this email to provide comments on the new Java 14 Record syntax.
> This new feature is very welcome, but the Kotlin syntax

Note that this feature is not unique to (or original with) Kotlin. The 
same syntax also shows up in C# and Scala.

> seems alien in

"Alien looking" is a common objection to new features.  Every 
significantly new feature is likely to have some syntactically new 
aspect, and it will be unfamiliar at first.  And with nearly every new 
feature, the "alien" complaint comes around again.  When generics came 
along, the outcry was "You're making Java look like C++!" (and this 
outcry was loud.)   When lambdas came along, it was "this doesn't look 
like Java.  Can't we use (this syntax that looks familiar to me from my 
other favorite language)?"

Fast forward, these features don't look alien to us at all now! They 
look like the language we know and love and are comfortable with.

This is not to say the syntax is necessarily _good_ (though I think it 
is); it is that the complain of "alien" is inherently a transient one.  
It will undoubtedly graduate to "familar" soon enough (though you might 
at that point still find it ugly.)

> I’d like to propose a syntax closer to the one for Java interfaces as shown
> below
>
> public record Product{
>          String name;
>          String description;
>          BigDecimal price;
> }

It should probably be no surprise that this suggestion has come up 
before, and was discussed and rejected.

One major point against it is that it trades prominent new syntax for a 
subtle new (alien!) behavior -- that changing the order of field 
declarations is now an incompatible change.  Java never worked this way 
before, and now, with the small change from "class" to "record", the 
field order matters, because it is baked into APIs. That's pretty bad!

Ignoring order of fields, such a syntax would also be brittle, as it 
lacks any cues to remind authors that the set of fields is not a mere 
implementation detail, but in fact a lightly encrypted public API.  
Because a record declaration looks like a constructor argument list, 
we're less likely to change it without analyzing the consequences, 
because it looks like an API.  But the declaration of fields has always 
been _just implementation_, and we generally feel much more free to muck 
with implementation, and might be surprised to find we've broken our 
clients.

Finally, it just doesn't reflect what records are.  It might have been 
more appropriate to the Billy Boilerplate vision for records, where (as 
with Lombok) records are a purely syntactic feature for hiding the 
boilerplate under the rug.  But that's not what records are.  Records 
are _nominal tuples_; they _are_ their data.  It is entirely appropriate 
for the data definition to be front and center in the declaration -- 
because that's what records are.  And, given that constructors (and 
eventually deconstructors) are invoked positionally, having the argument 
list appear somewhere in the declaration is important.

> This gives power to the developer extend and define the final behavior.

Ultimately, I think what you really wanted was that we selected a 
slightly different design center for this feature -- perhaps something 
that acted more like a macro processor.  And, as we wrote in 
http://cr.openjdk.java.net/~briangoetz/amber/datum.html at the beginning 
of this project, we knew the central challenge of this feature would be 
that everyone has their own slightly different vision for what it should 
be.

> 1. Even if all the methods should be overridable, some hints/keywords or
> annotations to not use a field in the generated methods would be a good
> addition.
>
> Because the developer may want to omit a field from the toString because it
> may contain sensitive information or GDPR information, and toStrings are
> usually dumped in the logs as is.

You of course have the option to write these as you did before records.  
That said, I think this comment belies the fact that you are viewing 
records as largely a syntactic convenience, but that's not what they 
are.  Records are a _semantic_ feature; they are the state, the whole 
state, and nothing but the state.  All their protocols -- construction, 
deconstruction, equality, hashing, string representation -- are derived 
mechanically from a common state description.  Routinely mucking with 
Object method implementations because not all fields are treated equally 
is a hint that what you're working with do not meet the semantic 
requirements to be records, and you're only using records for the 
syntax.  (We considered, briefly, making these methods not overridable, 
but unfortunately this was too restrictive (largely because of arrays.) 
But it is nearly guaranteed that overriding these will be overused.)

> 2. Some type annotation and some META-INF/“record” config file to set the
> naming strategy of the getter/accessor
> Just for the sake of backwards compatibility with the old naming convention.
>

The set of "code generation knobs" that have been, or could be, 
requested for this feature is potentially infinite; this is one of 
them.  In the end, we settled on a philosophy of "no knobs".  Of course, 
it is easy to say "but this one knob would solve my problem."  But I 
don't think it will.  Most code that uses the old conventions also do 
not meet the requirements for being a record (either because they have 
some non-final fields, or some fields without getters, or their 
constructor doesn't take all the components, or some components don't 
play into equals/hashCode/toString, etc), and so even if you had this 
knob, "for migration", it would only push the migration problem a little 
bit farther down the road.  And then you'd be asking for more knobs.

The reality is: if you're looking for a tool to automate the generation 
of JavaBean-style classes for your APIs, this isn't it. In fact, most 
APIs probably won't expose very many; we're far more likely to use them 
internally as implementation details.  And they're great for that!




More information about the amber-dev mailing list