Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8254944

[JEP 390] Revise "value-based class" & apply to wrappers

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P4
    • Resolution: Approved
    • Fix Version/s: 16
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Risk:
      minimal
    • Interface Kind:
      Java API
    • Scope:
      SE

      Description

      Summary

      Revise the definition of "value-based class" to more accurately match expected future behavior of primitive classes, and update cross-references from API classes. Make the primitive wrapper classes (Integer, Boolean, Double, etc.) value-based classes.

      Problem

      The primitive wrapper classes—Boolean, Character, Byte, Short, Integer, Long, Float, and Double—are slated to become primitive classes when the Valhalla project completes that feature. A value-based class in the current SE API claims a contract that is mostly compatible with eventually becoming a primitive class. To set programmers' expectations and smooth the transition, the primitive wrapper classes should thus adopt the value-based class terminology in their current specifications.

      Certain details of the value-based class specification are not compatible with the wrapper classes or with the future requirements of primitive classes. The specification can be refined to reflect the needs of these uses cases.

      Solution

      Update the value-based class specification as follows:

      • Allow for use of == on instances, as long as the class ensures that behavior is consistent between instances that are equal (per equals), and that factories never promise to return unique instances if results are equal.

      • Allow for non-private constructors if they are deprecated

      • Allow factory methods to make promises about identity of results (like cacheing), as long as they do not promise a unique identity on each call

      • Constrain classes to have no superclass fields or superclass initialization logic

      • Clarify the distinction between requirements for classes and expectations for clients

      Update the boilerplate used in references to this specification (links to ValueBased.html), allowing for use of ==, but emphasizing the importance of treating equal instances as interchangeable, and that synchronization should be avoided.

      Apply the boilerplate to the wrapper classes.

      The java.lang.ConstantDesc classes don't fully satisfy the revised contract—e.g., they often inherit fields from superclasses. Remove the "value-based class" designation, and just say that clients shouldn't depend on identity.

      We don't anticipate any negative compatibility impact. Third parties are not expected to declare their own value-based classes (this is an informal concept defined within the Java SE API to describe properties of its own classes). The expectations imposed on clients of value-based classes have been relaxed—they should continue to avoid synchronization, but some uses of == are okay. Of course, any further constraints imposed by the classes' own specifications remain in force.

      Specification

      Revised ValueBased.html:

       <body>
       <h1 id="ValueBased">{@index "Value-based Classes"}</h1>
      
      Some classes, such as <code>java.lang.Integer</code> and
      <code>java.time.LocalDate</code>, are <em>value-based</em>.
      A value-based class has the following properties:
       <ul>
          <li>the class declares only final instance fields (though these may contain references
              to mutable objects);</li>
          <li>the class's implementations of <code>equals</code>, <code>hashCode</code>,
              and <code>toString</code> compute their results solely from the values
              of the class's instance fields (and the members of the objects they
              reference), not from the instance's identity;</li>
          <li>the class's methods treat instances as <em>freely substitutable</em>
              when equal, meaning that interchanging any two instances <code>x</code> and
              <code>y</code> that are equal according to <code>equals()</code> produces no
              visible change in the behavior of the class's methods;</li>
          <li>the class performs no synchronization using an instance's monitor;</li>
          <li>the class does not declare (or has deprecated any) accessible constructors;</li>
          <li>the class does not provide any instance creation mechanism that promises
              a unique identity on each method call&mdash;in particular, any factory
              method's contract must allow for the possibility that if two independently-produced
              instances are equal according to <code>equals()</code>, they may also be
              equal according to <code>==</code>;</li>
          <li>the class is final, and extends either <code>Object</code> or a hierarchy of
              abstract classes that declare no instance fields or instance initializers
              and whose constructors are empty.</li>
       </ul>
      < p >When two instances of a value-based class are equal (according to 'equals'), a program
          should not attempt to distinguish between their identities, whether directly via reference
           equality or indirectly via an appeal to synchronization, identity hashing,
          serialization, or any other identity-sensitive mechanism.</p>
      < p >Synchronization on instances of value-based classes is strongly discouraged,
          because the programmer cannot guarantee exclusive ownership of the
          associated monitor.</p>
      < p >Identity-related behavior of value-based classes may change in a future release.
          For example, synchronization may fail.</p>
       </body>
       </html>

      ('p' tags have been tweaked to get them to render correctly in JBS.)

      Updated cross-reference boilerplate, applied to existing value-based classes and the primitive wrapper classes:

       * <p>This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
       * class; programmers should treat instances that are
       * {@linkplain #equals(Object) equal} as interchangeable and should not
       * use instances for synchronization, or unpredictable behavior may
       * occur. For example, in a future release, synchronization may fail.

      List of files with boilerplate spec updates (see attachment for diff):

      src/java.base/share/classes/java/lang/Boolean.java
      src/java.base/share/classes/java/lang/Byte.java
      src/java.base/share/classes/java/lang/Character.java
      src/java.base/share/classes/java/lang/Double.java
      src/java.base/share/classes/java/lang/Float.java
      src/java.base/share/classes/java/lang/Integer.java
      src/java.base/share/classes/java/lang/Long.java
      src/java.base/share/classes/java/lang/ProcessHandle.java
      src/java.base/share/classes/java/lang/Runtime.java
      src/java.base/share/classes/java/lang/Short.java
      src/java.base/share/classes/java/time/Duration.java
      src/java.base/share/classes/java/time/Instant.java
      src/java.base/share/classes/java/time/LocalDate.java
      src/java.base/share/classes/java/time/LocalDateTime.java
      src/java.base/share/classes/java/time/LocalTime.java
      src/java.base/share/classes/java/time/MonthDay.java
      src/java.base/share/classes/java/time/OffsetDateTime.java
      src/java.base/share/classes/java/time/OffsetTime.java
      src/java.base/share/classes/java/time/Period.java
      src/java.base/share/classes/java/time/Year.java
      src/java.base/share/classes/java/time/YearMonth.java
      src/java.base/share/classes/java/time/ZoneId.java
      src/java.base/share/classes/java/time/ZoneOffset.java
      src/java.base/share/classes/java/time/ZonedDateTime.java
      src/java.base/share/classes/java/time/chrono/HijrahDate.java
      src/java.base/share/classes/java/time/chrono/JapaneseDate.java
      src/java.base/share/classes/java/time/chrono/MinguoDate.java
      src/java.base/share/classes/java/time/chrono/ThaiBuddhistDate.java
      src/java.base/share/classes/java/util/KeyValueHolder.java
      src/java.base/share/classes/java/util/List.java
      src/java.base/share/classes/java/util/Map.java
      src/java.base/share/classes/java/util/Optional.java
      src/java.base/share/classes/java/util/OptionalDouble.java
      src/java.base/share/classes/java/util/OptionalInt.java
      src/java.base/share/classes/java/util/OptionalLong.java
      src/java.base/share/classes/java/util/Set.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/PaddingLayout.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java
      src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java
      test/lib/jdk/test/lib/hexdump/HexPrinter.java

      Example spec change for java.lang.constant.ConstantDesc, java.lang.constant.DynamicCallSiteDesc, and java.lang.constant.DynamicConstantDesc:

      - * <p>Implementations of {@linkplain ConstantDesc} must be
      - * <a href="../doc-files/ValueBased.html">value-based</a> classes.
      + * <p>Implementations of {@linkplain ConstantDesc} should be immutable
      + * and their behavior should not rely on object identity.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              dlsmith Dan Smith
              Reporter:
              dlsmith Dan Smith
              Reviewed By:
              Brian Goetz
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: