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

Refine the spec of equals() and hashCode() for j.text.Format classes

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 22
    • core-libs
    • None
    • behavioral
    • minimal
    • A specification only change to elaborate on the spec of equals and hashCode for j.text.Format related classes.
    • Java API
    • SE

      Summary

      Expand the under-specified documentation of the equals and hashCode methods of java.text.Format related classes.

      Problem

      The current specification for most of these methods is either "Overrides method_name" or are incomplete. This does not provide the necessary information for users to use/override them.

      Solution

      Provide a clear, concise, and correct specification for the two methods.

      equals()

      Ensure that implementers utilize a getClass() over instanceof notion of class hierarchy (enforced using @implSpec) so that they obey the general equals contract, specifically the quality of symmetry.

      hashCode()

      The exisiting hashCode methods differ in that some implementations use a few fields while others use almost all possible serialized fields. Where only a few fields are used, specifically provide the associated getters in the definition.

      For the methods that use a number of fields where it is no longer concise to list out all the fields, use the following wording: "Non-transient instance fields of this class are used to calculate a hash code value which adheres to the contract defined in {@link Objects#hashCode}". This provides an accurate and concise definition. For implementers desiring more specificity, they can view the serialized form linked in the class description.

      Specify to implementers that they do not need to provide a consistent hash code value in their implementations, as a getClass() notion of class hierarchy is used, and thus instances of the sub class should not compare equal to the base class.

      Specification

      All of the X_Format.java classes follow the same wording structure for equals. The two classes not following this structure are DateFormatSymbols.java and DecimalFormatSymbols.java. The hashCode specifications vary.

      ChoiceFormat.java

           /**
      -     * Generates a hash code for the message format object.
      +     * {@return the hash code for this {@code ChoiceFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value using the values
      +     * returned by {@link #getFormats()} and {@link #getLimits()}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {
      
           /**
      -     * Equality comparison between two
      +     * Compares the specified object with this {@code ChoiceFormat} for equality.
      +     * Returns true if the object is also a {@code ChoiceFormat} and the
      +     * two formats would format any value the same.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code ChoiceFormat}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj) {

      CompactNumberFormat.java

           /**
      -     * Checks if this {@code CompactNumberFormat} is equal to the
      -     * specified {@code obj}. The objects of type {@code CompactNumberFormat}
      -     * are compared, other types return false; obeys the general contract of
      -     * {@link java.lang.Object#equals(java.lang.Object) Object.equals}.
      +     * Compares the specified object with this {@code CompactNumberFormat} for equality.
      +     * Returns true if the object is also a {@code CompactNumberFormat} and the
      +     * two formats would format any value the same.
            *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
            * @param obj the object to compare with
            * @return true if this is equal to the other {@code CompactNumberFormat}
      +     * @see Object#hashCode()
            */
           @Override
           public boolean equals(Object obj) {
      
           /**
      -     * {@return the hash code for this {@code CompactNumberFormat} instance}
      +     * {@return the hash code for this {@code CompactNumberFormat}}
      +     *
      +     * @implSpec Non-transient instance fields of this class are used to calculate
      +     * a hash code value which adheres to the contract defined in {@link Objects#hashCode}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {

      DateFormat.java

           /**
      -     * Overrides hashCode
      +     * {@return the hash code for this {@code DateFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value using the value
      +     * returned by {@link #getNumberFormat()}.
      +     * @see Object#hashCode()
            */
           public int hashCode() {
      
           /**
      -     * Overrides equals
      +     * Compares the specified object with this {@code DateFormat} for equality.
      +     * Returns true if the object is also a {@code DateFormat} and the
      +     * two formats would format any value the same.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code DateFormat}
      +     * @see Object#equals(Object)
            */
           public boolean equals(Object obj) {

      DateFormatSymbols.java

           /**
      -     * Override hashCode.
      -     * Generates a hash code for the DateFormatSymbols object.
      +     * {@return the hash code for this {@code DateFormatSymbols}}
      +     *
      +     * @implSpec Non-transient instance fields of this class are used to calculate
      +     * a hash code value which adheres to the contract defined in {@link Objects#hashCode}
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {
      
           /**
      -     * Override equals
      +     * Compares the specified object with this {@code DateFormatSymbols} for equality.
      +     * Returns true if the object is also a {@code DateFormatSymbols} and the two
      +     * {@code DateFormatSymbols} objects represent the same date-time formatting data.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code DateFormatSymbols}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj)

      DecimalFormat.java

           /**
      -     * Overrides equals
      +     * Compares the specified object with this {@code DecimalFormat} for equality.
      +     * Returns true if the object is also a {@code DecimalFormat} and the
      +     * two formats would format any value the same.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code DecimalFormat}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj)
      
           /**
      -     * Overrides hashCode
      +     * {@return the hash code for this {@code DecimalFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value using the values returned from
      +     * {@link #getPositivePrefix()} and {@link NumberFormat#hashCode()}.
      +     * @see Object#hashCode()
      +     * @see NumberFormat#hashCode()
            */
           @Override
           public int hashCode() {

      DecimalFormatSymbols.java

           /**
      -     * Override equals.
      +     * Compares the specified object with this {@code DecimalFormatSymbols} for equality.
      +     * Returns true if the object is also a {@code DecimalFormatSymbols} and the two
      +     * {@code DecimalFormatSymbols} objects represent the same set of symbols.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code DecimalFormatSymbols}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj) {
      
           /**
      -     * Override hashCode.
      +     * {@return the hash code for this {@code DecimalFormatSymbols}}
      +     *
      +     * @implSpec Non-transient instance fields of this class are used to calculate
      +     * a hash code value which adheres to the contract defined in {@link Objects#hashCode}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {

      MessageFormat.java

           /**
      -     * Equality comparison between two message format objects
      +     * Compares the specified object with this {@code MessageFormat} for equality.
      +     * Returns true if the object is also a {@code MessageFormat} and the
      +     * two formats would format any value the same.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code MessageFormat}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj) {
      
           /**
      -     * Generates a hash code for the message format object.
      +     * {@return the hash code value for this {@code MessageFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value using the value
      +     * returned by {@link #toPattern()}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {

      NumberFormat.java

           /**
      -     * Overrides hashCode.
      +     * {@return the hash code for this {@code NumberFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value using the values returned by
      +     * {@link #getMaximumIntegerDigits()} and {@link #getMaximumFractionDigits()}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode() {
      
           /**
      -     * Overrides equals.
      +     * Compares the specified object with this {@code NumberFormat} for equality.
      +     * Returns true if the object is also a {@code NumberFormat} and the
      +     * two formats would format any value the same.
      +     *
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code NumberFormat}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj) {

      SimpleDateFormat.java

           /**
      -     * {@return the hash code value for this {@code SimpleDateFormat} object}
      +     * {@return the hash code value for this {@code SimpleDateFormat}}
      +     *
      +     * @implSpec This method calculates the hash code value the value returned by
      +     * {@link #toPattern()}.
      +     * @see Object#hashCode()
            */
           @Override
           public int hashCode()
      
           /**
      -     * Compares the given object with this {@code SimpleDateFormat} for
      -     * equality.
      +     * Compares the specified object with this {@code SimpleDateFormat} for equality.
      +     * Returns true if the object is also a {@code SimpleDateFormat} and the
      +     * two formats would format any value the same.
            *
      -     * @return true if the given object is equal to this
      -     * {@code SimpleDateFormat}
      +     * @implSpec This method performs an equality check with a notion of class
      +     * identity based on {@code getClass()}, rather than {@code instanceof}.
      +     * Therefore, in the equals methods in subclasses, no instance of this class
      +     * should compare as equal to an instance of a subclass.
      +     * @param  obj object to be compared for equality
      +     * @return {@code true} if the specified object is equal to this {@code SimpleDateFormat}
      +     * @see Object#equals(Object)
            */
           @Override
           public boolean equals(Object obj)

            jlu Justin Lu
            xwangsunw Xiaozhong Wang (Inactive)
            Naoto Sato
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: