toString(), equals() Contract

Any Object is an Object or a child of an Object as described in the Java Language Specification:

The class Object is a super class (§8.1) of all other classes. A variable of type Object can hold a reference to the null reference or to any object, whether it is an instance of a class or an array (§10). All class and array types inherit the methods of class Object[…]

JLS – 4.3.2

The Object implements the following methods:

I want to elaborate on the methods public String toString(), public boolean equals(Object obj), public int hashCode(). I want to clear what are they for and when and how you should overwrite them. All of these methods are not final and can be overwritten.

Let’s start with public String toString().

toString() is mostly called implicit (internal without your assistance) but can also called explicit (with your assistance).
A good example for an implicit call is System.out.println():

alf.toString() is actually called/searched in Person but not found. So the procedure is repeated in the next closer parent class until the method is found (in this case Object, because Person has no base class. You could also read this as Person extends Object). This mechanism is called Dynamic Binding.

This example would print something like equalsContract.Example$Person@dc8569 (it’s a combination of the classname and the hashCode) which is not very useful. We could approve this example by overwriting the toString() method by our own. So we could print something more meaningful.

The new toString() method returns now information about the object state. By overwriting this method the call alf.toString() is successfully now.

The output is: name='Alf', age='32'.

Info

I recommend to overwrite the toString() method – this gives you more easy readable information about the object state.


The boolean equals(Object obj) is very important in combination with the java collections framework. For example if you would like to check if an collection contains an specific object:

contains(Object o) would call the default implementation of equals(Object o) for each item. Each item in the list would be compared with the passed Object. The composition is done by calling the equals(Object o) method. Since each object is unique in Java this Person would not be found.

But we could overwrite the equals() method with the knowledge of what makes a Person unique.

Javadoc

The javadoc of the equals functions lists various specifications about what the equals function must cover (the equals contract): Indicates whether some other object is “equal to” this one.

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

With this knowledge we can overwrite the equals method:

Now the person was found in the list. The output is true.

Sources:

http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html
Book – Der Weg zum Java-Profi http://dpunkt.de/buecher/3810/der-weg-zum-java-profi.html

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.