Draft specification for java.lang.Record

Alex Buckley alex.buckley at oracle.com
Thu Aug 15 19:14:04 UTC 2019


I am reading this javadoc from the POV of someone in 2034 (15 years 
hence, like we are 15 years from Enum) who doesn't know anything about 
Amber.

On 8/15/2019 10:34 AM, Brian Goetz wrote:
> /**
>   * This is the common base class of all Java language record classes.

I know this borrows from Enum, but "base class" is a terrible un-Java 
phrase there and it's terrible here.  "This is the common superclass of 
all record classes in the Java language."

>   *
>   * <p>More information about records, including descriptions of the
>   * implicitly declared methods synthesized by the compiler, can be
>   * found in section 8.10 of
>   * <cite>The Java™ Language Specification</cite>.

Too much too soon; drop.

>   *
>   * <p>A <em>record class</em> is a shallowly immutable, transparent 
> carrier for
>   * a fixed set of values, called the <em>record components</em>.  The 
> Java™
>   * language provides concise syntax for declaring record classes, 
> whereby the
>   * record components are declared in the record header.  The list of record
>   * components declared in the record header form the <em>record 
> descriptor</em>.

Are classes immutable, or objects? I think "shallowly immutable" belongs 
in a paragraph about "records" or "record instances" (not "record 
classes") that is not yet written, but should appear just before "For 
all record classes, ..."

>   *
>   * <p>A record class has the following mandated members: a public 
> <em>canonical
>   * constructor</em>, whose descriptor is the same as the record descriptor;

"A record class has a public canonical constructor, whose signature is 
the same ...;"

>   * a private ... field corresponding to each component, whose name and
>   * type are the same as that of the component; a public accessor method
>   * corresponding to each component, whose name and return type are the 
> same as
>   * that of the component.  If not explicitly declared in the body of 
> the record,

Prefer "; and a public _no-args_ accessor method corresponding ...  Any 
or all of these elements may be declared explicitly; if one is not 
declared explicitly, then it is provided implicitly."

>   * implicit implementations for these members are provided.
>   *
>   * <p>The implicit declaration of the canonical constructor initializes the
>   * component fields from the corresponding constructor arguments. The 
> implicit
>   * declaration of the accessor methods returns the value of the 
> corresponding
>   * component field.  The implicit declaration of the {@link 
> Object#equals(Object)},
>   * {@link Object#hashCode()}, and {@link Object#toString()} methods are 
> derived
>   * from all of the component fields.
>   *
>   * <p>The primary reasons to provide an explicit declaration for the
>   * canonical constructor or accessor methods are to validate constructor
>   * arguments, perform defensive copies on mutable components, or 
> normalize groups
>   * of components (such as reducing a rational number to lowest terms.)  
> If any
>   * of these are provided explicitly.

Can't grok "mutable components". Do you mean the (mutable) constructor 
arguments which correspond to components?

Prefer ", or cross-check the values of different components." instead of 
normalizing and reducing which again is hard to follow.

Expecting: "An instance of a record class is _shallowly immutable_, 
which means ..."

>   *
>   * <p>For all record classes, the following invariant must hold: if a 
> record R's
>   * components are {@code c1, c2, ... cn}, then if a record instance is 
> copied
>   * as follows:

Calling `R` a "record" is obtuse since the invariant is about "record 
classes" and this whole spec outlines a "record class". There should be 
two kinds of entity -- "record class" and "record instance", or "record 
class" and "record" -- not three. Also, "Given a non-null instance `r` 
of record class `R`, whose components are ..., then if `r` is copied in 
the following way:"

>   * <pre>
>   *     R copy = new R(r.c1(), r.c2(), ..., r.cn());
>   * </pre>
>   * then it must be the case that {@code r.equals(copy)}.

A name like "copy equality" or "by parts equality" or "component 
equality" would be helpful for this property, both for the spec of 
equals and for developers' general knowledge.

Cloning: if a record class was to implement Cloneable, then the 
inherited implementation of Object::clone would not preserve copy 
equality (because, yes, cloning is not the same as copying). Recommend 
not implementing Cloneable?

Alex


More information about the amber-spec-experts mailing list