JDK-8253605 : implementing Record Classes as a standard feature in Java
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 16
  • Submitted: 2020-09-24
  • Updated: 2020-12-04
  • Resolved: 2020-10-16
Related Reports
CSR :  
CSR :  
Relates :  
Relates :  
Relates :  
Description
Summary
-------

Record Classes were originally proposed by JEP 359 in early 2019. JEP 359 was targeted to JDK 14 as a preview feature. Feedback on the feature was positive but it was suggested that the feature should be previewed again, to gain more experience. Some changes were proposed including relaxing the requirement that canonical constructor must be `public`, along with support for local enum classes and interfaces (alongside local record classes). The feature was previewed a second time by JEP 384 which was targeted to JDK 15. Feedback on JDK 15 suggests that the Record Classes feature is now ready to be made final and permanent.

Problem
-------

The preview status of Record Classes prevents usage in standard Java.

Solution
--------

Remove the preview status requirement from Record Classes.

Specification
-------------

This CSR is concerned only with removing the preview status from the Java API. The changes are listed below.

Java API

    diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
    index 1fabad43738..5c64ababc11 100644
    --- a/src/java.base/share/classes/java/lang/Class.java
    +++ b/src/java.base/share/classes/java/lang/Class.java
         /**
    -     * {@preview Associated with records, a preview feature of the Java language.
    -     *
    -     *           This method is associated with <i>records</i>, a preview
    -     *           feature of the Java language. Preview features
    -     *           may be removed in a future release, or upgraded to permanent
    -     *           features of the Java language.}
    -     *
          * Returns an array of {@code RecordComponent} objects representing all the
          * record components of this record class, or {@code null} if this class is
          * not a record class.
    @@ -2385,11 +2378,8 @@ public Method getMethod(String name, Class<?>... parameterTypes)
          *          </ul>
          *
          * @jls 8.10 Record Types
    -     * @since 14
    +     * @since 16
          */
    -    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                                 essentialAPI=false)
    -    @SuppressWarnings("preview")
         @CallerSensitive
         public RecordComponent[] getRecordComponents() {
             SecurityManager sm = System.getSecurityManager();
    @@ -3688,13 +3678,6 @@ public boolean isEnum() {
         }
     
         /**
    -     * {@preview Associated with records, a preview feature of the Java language.
    -     *
    -     *           This method is associated with <i>records</i>, a preview
    -     *           feature of the Java language. Preview features
    -     *           may be removed in a future release, or upgraded to permanent
    -     *           features of the Java language.}
    -     *
          * Returns {@code true} if and only if this class is a record class.
          *
          * <p> The {@linkplain #getSuperclass() direct superclass} of a record
    @@ -3707,10 +3690,8 @@ public boolean isEnum() {
          *
          * @return true if and only if this class is a record class, otherwise false
          * @jls 8.10 Record Types
    -     * @since 14
    +     * @since 16
          */
    -    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                                 essentialAPI=false)
         public boolean isRecord() {
             return getSuperclass() == JAVA_LANG_RECORD_CLASS && isRecord0();
         }
    diff --git a/src/java.base/share/classes/java/lang/Record.java b/src/java.base/share/classes/java/lang/Record.java
    index 4d568e8baa0..121fc7ce73c 100644
    --- a/src/java.base/share/classes/java/lang/Record.java
    +++ b/src/java.base/share/classes/java/lang/Record.java
    @@ -25,14 +25,6 @@
     package java.lang;
     
     /**
    - * {@preview Associated with records, a preview feature of the Java language.
    - *
    - *           This class is associated with <i>records</i>, a preview
    - *           feature of the Java language. Programs can only use this
    - *           class when preview features are enabled. Preview features
    - *           may be removed in a future release, or upgraded to permanent
    - *           features of the Java language.}
    - *
      * This is the common base class of all Java language record classes.
      *
      * <p>More information about records, including descriptions of the
    @@ -86,10 +78,8 @@
      * <a href="{@docRoot}/java.base/java/io/ObjectInputStream.html#record-serialization">record serialization</a>.
      *
      * @jls 8.10 Record Types
    - * @since 14
    + * @since 16
      */
    -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                             essentialAPI=true)
     public abstract class Record {
         /**
          * Constructor for record classes to call.
    diff --git a/src/java.base/share/classes/java/lang/annotation/ElementType.java b/src/java.base/share/classes/java/lang/annotation/ElementType.java
    index 15182f2a87b..db4e65a2b45 100644
    --- a/src/java.base/share/classes/java/lang/annotation/ElementType.java
    +++ b/src/java.base/share/classes/java/lang/annotation/ElementType.java
    @@ -118,22 +118,12 @@
         MODULE,
     
         /**
    -     * {@preview Associated with records, a preview feature of the Java language.
    -     *
    -     *           This constant is associated with <i>records</i>, a preview
    -     *           feature of the Java language. Programs can only use this
    -     *           constant when preview features are enabled. Preview features
    -     *           may be removed in a future release, or upgraded to permanent
    -     *           features of the Java language.}
    -     *
          * Record component
          *
          * @jls 8.10.3 Record Members
          * @jls 9.7.4 Where Annotations May Appear
          *
    -     * @since 14
    +     * @since 16
          */
    -    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                                 essentialAPI=true)
         RECORD_COMPONENT;
     }
    diff --git a/src/java.base/share/classes/java/lang/reflect/RecordComponent.java b/src/java.base/share/classes/java/lang/reflect/RecordComponent.java
    index 225a0999f17..7079f3d28f7 100644
    --- a/src/java.base/share/classes/java/lang/reflect/RecordComponent.java
    +++ b/src/java.base/share/classes/java/lang/reflect/RecordComponent.java
    @@ -38,23 +38,14 @@
     import java.util.Objects;
     
     /**
    - * {@preview Associated with records, a preview feature of the Java language.
    - *
    - *           This class is associated with <i>records</i>, a preview
    - *           feature of the Java language. Preview features
    - *           may be removed in a future release, or upgraded to permanent
    - *           features of the Java language.}
    - *
      * A {@code RecordComponent} provides information about, and dynamic access to, a
      * component of a record class.
      *
      * @see Class#getRecordComponents()
      * @see java.lang.Record
      * @jls 8.10 Record Types
    - * @since 14
    + * @since 16
      */
    -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                             essentialAPI=false)
     public final class RecordComponent implements AnnotatedElement {
         // declaring class
         private Class<?> clazz;
    diff --git a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java
    index f1115b6c36d..ad50a002f71 100644
    --- a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java
    +++ b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java
    @@ -38,23 +38,14 @@
     import java.util.Objects;
     
     /**
    - * {@preview Associated with records, a preview feature of the Java language.
    - *
    - *           This class is associated with <i>records</i>, a preview
    - *           feature of the Java language. Preview features
    - *           may be removed in a future release, or upgraded to permanent
    - *           features of the Java language.}
    - *
      * Bootstrap methods for state-driven implementations of core methods,
      * including {@link Object#equals(Object)}, {@link Object#hashCode()}, and
      * {@link Object#toString()}.  These methods may be used, for example, by
      * Java compiler implementations to implement the bodies of {@link Object}
      * methods for record classes.
      *
    - * @since 14
    + * @since 16
      */
    -@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                             essentialAPI=false)
     public class ObjectMethods {
     
         private ObjectMethods() { }
    diff --git a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java
    index 6fc8ad93384..bcd0761dfa6 100644
    --- a/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java
    +++ b/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java
    @@ -92,16 +92,8 @@ public LocationInfo getLocationInfo() {
             METHOD_FORMAL_PARAMETER,
             THROWS,
             /**
    -         * {@preview Associated with records, a preview feature of the Java language.
    -         *
    -         *           This enum constant is associated with <i>records</i>, a preview
    -         *           feature of the Java language. Preview features
    -         *           may be removed in a future release, or upgraded to permanent
    -         *           features of the Java language.}
    -         * @since 14
    +         * @since 16
              */
    -        @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
    -                                     essentialAPI=false)
             RECORD_COMPONENT;
         }


Comments
[~darcy] Thanks for the comments. I attach the updated specs along with diff files showing precisely what changed between the specs.
04-12-2020

A retroactive review on the non-API parts of this request: [~gbierman], some updates are needed: records-jls.html The following are essential API elements associated with Record Types: The class java.lang.Record. The enum constant RECORD_COMPONENT in java.lang.annotation.ElementType. The API is no longer preview so this should be removed. Note that isKeyword like methods in javax.lang.model do not need to be updated for "record". The equals behavior for records is incorrect and out of sync with the API spec: > A method public final boolean equals(Object obj) that returns true if > and only if the argument is an instance of the same record class, and > each record component of this record is equal to the corresponding > record component of the argument, according to the equals method of > class Object for record components whose types are reference types, > and == for record components whose types are primitive types. tl;dr -- this doesn't implement the desired semantics for NaN floating-point values of the float and double double. Please see API spec: https://download.java.net/java/early_access/jdk16/docs/api/java.base/java/lang/Record.html#equals(java.lang.Object) for comparison. JVMS Table 4.7-A and 4.7-B, 4.7-C,update the class file version 60 and JDK 16.
07-11-2020

Joe Darcy I attached the latest builds of the specs FYI
03-11-2020

[~darcy] thanks for the approval
17-10-2020

Moving to Approved.
16-10-2020

Adjusting component/subcomponent and interface kind if this issue is only for the API changes.
14-10-2020

[~darcy] I have updated the Specification section stating that this particular CSR is concerned with removing the `preview` status from the Java API. There are other related CSRs like JDK-8253895 which addresses the changes to the javax.lang.model and JDK-8254321 which addresses statics in inner classes.
14-10-2020

[~vromero], please clarify which particular changes this CSR is intended to cover in addition to referencing the related documents. Moving to Provisional, but please make the updates before Finalizing.
14-10-2020

note: although this CSR's specification section mentions all the new changes in the records spec, there are additional CSRs that address specific changes and which are related to narrower implementation changes: - JDK-8254321, addresses static definitions in inner classes - JDK-8253895, addresses changes to javax.lang.model APIs - JDK-8254331, new restrictions on annotations of record components
09-10-2020

[~darcy]I think I have addressed all the comments above, please ignore the PDF file, it is outdated now. I have uploaded a new zip file which contains the missing files. The javax.lang.model changes will be listed in a separate CSR
06-10-2020

Moving to Provisional. Before this request is finalized please: * Explicitly list the spec changes from the prior preview in the specification section; from the pdf attachment: > The changes are the same as those in the second preview ��� of Records in Java SE 15, except for minor editorial changes and the following: > - To relax the current restriction on an inner class from declaring a member that is explicitly or implicitly static. This will now be permitted and, in particular, will allow an inner class to declare a record class member. (These changes are detailed in the document on Local Static Interfaces and Enum Classes.) >- Add text to explicitly rule out using C-style array declaration of record components. >- Clarify that any annotations on record components that apply to the implicitly declared accessor method must satisfy the existing rules for annotating a method declaration. * Include any documents for the JVMS changes and serialization changes. * The pdf document has a "Preview Features" section; presumably this should be removed or modified. * As an RFE, the JLS change pdf does not have all the bells and whistles of the added/removed text markup. Additionally, the HTML files in the zip archive do not have the full CSS markup. * Any API changes in java.base should be covered in this CSR or another CSR. If covered in this CSR, the Interface list should be expanded to include "Java API". * The API changes for javax.lang.model should be explicitly listed in a CSR for that change.
30-09-2020

Note: even though the attached specification has a wider scope, in particular in the area referring to statics in inner classes, this CSR and related implementation changes are concerned only on removing the preview and related annotations from APIs and, for the implementation in particular the --enable-preview option for tests. The statics in inner issue will be addressed in a parallel CSR and implementation change.
30-09-2020