Another syntax for Java records
Brian Goetz
brian.goetz at oracle.com
Tue Nov 22 21:41:34 UTC 2022
To answer your question, we have to go back to "what were we trying to
accomplish with records in the first place." The obvious-but-wrong
answer is "to free Java developers of the tyranny of boilerplate."
That's an important benefit, but that's a consequence, not the main
goal, of the records design.
Another way to say this is that records are not just about "make me the
implementation of the data-carrying class that I want"; they are not an
"implementation generator" like Lombok or Joda Beans or Immutables or
AutoValue. Yes, they do some implementation lifting, but they also make
promises to clients as well.
The list of components in the record header -- the state description --
is used to imply a contract:
- the class has a constructor whose argument list matches exactly the
state description
- the class has a deconstruction pattern whose binding list matches
exactly the state description
- the class has accessors for every component in the state description
- the class has an equals/hashCode/toString derived from the state
description
- the class adheres to a contract that couples the constructor,
accessors, and equals method, which says that if you take apart a record
with the accessors, and feed the results back to the constructor, you
get back an equivalent (according to equals) record.
All of these are derived from the state description, and can be counted
on by clients. That is why the state description is part of the record
declaration, not just implied by the fields. (It is also what lets us
derive a stronger serialization protocol for records, and in the future,
`with` expressions.)
This is an example of "get the semantics right and the syntax takes care
of itself." Records have semantics that permits us to boil away the
syntax, not the other way around.
If that's not enough, here's a less philosophical answer why your
approach would be dangerous. If you could declare
record R {
String r;
int x;
}
then the implied constructor would take a String and an int. But we are
used to being able to freely reorder field and method declarations; this
has always been a source-, binary-, and behavior-compatible change. But
in your model, reordering fields would reorder the parameters of the
constructor, breaking clients (sometimes silently, if you have a record
whose fields are all the same type.)
On 11/22/2022 4:25 PM, Heinzl, Steffen wrote:
>
> Hi!
>
> I wanted to suggest (if not yet done) to another syntax to Java records.
>
> I don’t quite understand the idea behind the syntax except that some
> other programming languages do it similar.
>
> A Java class looks like this:
>
> public class MyClass
>
> {
>
> String s;
>
> void myMethod(String a, int b);
>
> }
>
> An interface looks like this:
>
> public interface MyInterface
>
> {
>
> void myMethod(String c, String d);
>
> }
>
> Why all of a sudden is it a good idea to change that syntax to:
>
> public record MyRecord(String r, int x)
>
> {
>
> }
>
> instead of the following syntax (which is also possible in C# by the way)
>
> public record MyRecord
>
> {
>
> String r;
>
> int x;
>
> }
>
> I’m teaching Java and I find it strange from a lecturer’s point of
> view to explain the rationale for introducing the syntax like that.
> I’d be glad if someone could enlighten me!
>
> Thanks! Best,
>
> Steffen
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221122/5b490757/attachment-0001.htm>
More information about the amber-dev
mailing list