The Objects Class – Object Comparison


14.1 The Objects Class

The following static methods of the java.util.Objects class are convenient to use when comparing objects and computing the hash code for an object. They take away the drudgery of checking references for null values before calling them and never throw a NullPointerException—that is, they are null-safe.

Click here to view code image

static boolean equals(Object obj1, Object obj2)

Returns true if the arguments are equal to each other; otherwise, it returns false. This means that if both arguments are null, true is returned and if only one argument is null, false is returned. Equality is determined by invoking the equals() method on the first argument: obj1.equals(obj2). It is a convenience method for the Object.equals() method (Example 14.3, p. 748).

Click here to view code image

static int hash(Object… values)
static int hashCode(Object obj)

The first method generates a hash code for a sequence of specified values. It is useful for computing the hash code for objects containing multiple fields that are passed as arguments (Example 14.6, p. 771).

The second method computes and returns the hash code of a non-null argument; otherwise, it returns 0 for a null argument.

Both methods are convenience methods for the Object.hashCode() method.

Click here to view code image

static <T> int compare(T t1, T t2, Comparator<? super T> cmp)

Returns 0 if the arguments are identical; otherwise, it calls cmp.compare(t1, t2), which is the abstract method in the Comparator<T> interface. It also returns 0 if both arguments are null (Example 14.8, p. 777).

14.2 Implementing the equals() Method

If every object is to be considered unique, then it is not necessary to override the equals() method in the Object class. This method implements object reference equality. It implements the most discriminating equivalence relation possible on objects. Each instance of the class is only equal to itself.

Click here to view code image

public boolean equals(Object obj)

The equals() method in the Object class tests for object reference equality, the same as the == operator. It returns true only if the two references compared denote the same object—that is, if they are aliases. The equals() method is usually overridden to provide the semantics of object value equality, as in the case of the wrapper classes and the String class.

As a running example, we will implement different versions of a class for version numbers. A version number (VNO) for a software product comprises three pieces of information:

  • A release number
  • A revision number
  • A patch number

The idea is that releases do not happen very often. Revisions take place more frequently than releases, but less frequently than code patches are issued. We can say that the release number is most significant. The revision number is less significant than the release number, and the patch number is the least significant of the three fields. This ranking would also be employed when ordering version numbers chronologically.

Example 14.1 Not Overriding the Object.equals() Method

Click here to view code image

/** A simple version number class */
public class SimpleVNO {
  private int release;
  private int revision;
  private int patch;
  public SimpleVNO(int release, int revision, int patch) {
    this.release  = release;
    this.revision = revision;
    this.patch    = patch;
  }
  public int getRelease()  { return this.release;  }
  public int getRevision() { return this.revision; }
  public int getPatch()    { return this.patch;    }

  @Override public String toString() {
    return “(” + release + “.” + revision + “.” + patch + “)”;
  }
}

The class SimpleVNO in Example 14.1 does not override the equals() method in the Object class. It only overrides the toString() method to generate a meaningful text representation for a version number.

The class TestSimpleVNO in Example 14.2 creates objects of the class SimpleVNO in Example 14.1 to test for object reference equality and object value equality. The output from Example 14.2 demonstrates that all SimpleVNO objects are unique because the class SimpleVNO does not override the equals() method to provide any other equivalence relation. The result of the == operator is always false for object reference equality, since all SimpleVNO objects are unique. An attempt is made to compare SimpleVNO objects for object value equality using the Object.equals() method, but the implementation of the Object.equals() method tests for object reference equality, the same as the == operator. Not surprisingly, the equals() method returns false even for SimpleVNO objects that have the same state (svno1 and svno2).

Example 14.2 Implications of Not Overriding the Object.equals() Method

Click here to view code image

import static java.lang.System.out;
public class TestSimpleVNO {
  public static void main(String[] args) {
    // Print name of version number class:
    out.println(SimpleVNO.class);
    // Three individual version numbers.
    SimpleVNO svno1 = new SimpleVNO(9,1,1);                        // (1)
    SimpleVNO svno2 = new SimpleVNO(9,1,1);                        // (2)
    SimpleVNO svno3 = new SimpleVNO(6,6,6);                        // (3)
    out.printf (”  svno1: %s, svno2: %s, svno3: %s%n”, svno1, svno2, svno3);
    out.println(“Test object reference equality:”);                // (4)
    out.println(”  svno1 == svno2:      ” + (svno1 == svno2));     // (5)
    out.println(”  svno1 == svno3:      ” + (svno1 == svno3));     // (6)
    out.println(“Test object value equality:”);
    out.println(”  svno1.equals(svno2): ” + svno1.equals(svno2));  // (7)
    out.println(”  svno1.equals(svno3): ” + svno1.equals(svno3));  // (8)
  }
}

Output from the program:

Click here to view code image

class SimpleVNO
  svno1: (9.1.1), svno2: (9.1.1), svno3: (6.6.6)
Test object reference equality:
  svno1 == svno2:      false
  svno1 == svno3:      false
Test object value equality:
  svno1.equals(svno2): false
  svno1.equals(svno3): false

Leave a Reply

Your email address will not be published. Required fields are marked *