10.2 The 'Object' Class

All classes extend the Object class, either directly or indirectly. A class declaration, without the extends clause, implicitly extends the Object class (see Section 6.1, p. 226). Thus, the Object class is always at the top of any inheritance hierarchy. The Object class defines the basic functionality that all objects exhibit and that all classes inherit. Note that this also applies for arrays, since these are genuine objects in Java.

The Object class provides the following general utility methods (see Example 10.1 for usage of some of these methods):

int hashCode()

When storing objects in hash tables, this method can be used to get a hash value for an object. This value is guaranteed to be consistent during the execution of the program. For a detailed discussion of the hashCode() method, see Section 11.7 on page 461.

boolean equals(Object obj)

Object reference and value equality are discussed together with the == and != operators (see Section 3.10, p. 68). The equals() method in the Object class returns true only if the two references compared denote the same object. The equals() method is usually overridden to provide the semantics of object value equality, as is the case for the wrapper classes and the String class. For a detailed discussion of the equals() method, see Section 11.7 on page 461.

final Class getClass()

Returns the runtime class of the object, which is represented by an object of the class java.lang.Class at runtime.

protected Object clone() throws CloneNotSupportedException

New objects that are exactly the same (i.e., have identical states) as the current object can be created by using the clone() method, that is, primitive values and reference values are copied. This is called shallow copying. A class can override this method to provide its own notion of cloning. For example, cloning a composite object by recursively cloning the constituent objects is called deep copying.

When overridden, the method in the subclass is usually declared public to allow any client to clone objects of the class.

If the overriding clone() method relies on the clone() method in the Object class, then the subclass must implement the Cloneable marker interface to indicate that its objects can be safely cloned. Otherwise, the clone() method in the Object class will throw a checked CloneNotSupportedException.

String toString()

If a subclass does not override this method, it returns a textual representation of the object, which has the following format:

"<name of the class>@<hash code value of object>"

This method is usually overridden and used for debugging purposes. The method call System.out.println(objRef) will implicitly convert its argument to a textual representation using the toString() method. See also the binary string concatenation operator +, discussed in Section 3.6 on page 62.

protected void finalize() throws Throwable

This method is discussed in connection with garbage collection (see Section 8.1, p. 324). It is called on an object just before it is garbage collected, so that any cleaning up can be done. However, the default finalize() method in the Object class does not do anything useful.

In addition, the Object class provides support for thread communication in synchronized code, through the following methods, which are discussed in Section 9.5 on page 370:

final void wait(long timeout) throws InterruptedException
final void wait(long timeout, int nanos) throws InterruptedException
final void wait() throws InterruptedException
final void notify()
final void notifyAll()

A thread invokes these method on the object whose lock it holds. A thread waits for notification by another thread.

Example 10.1 Methods in the Object class
public class ObjectMethods {
    public static void main(String[] args) {
        // Two objects of MyClass.
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();

        // Two strings.
        String str1 = new String("WhoAmI");
        String str2 = new String("WhoAmI");

        // Method hashCode() overridden in String class.
        // Strings with same content (i.e., are equal) have the same hash code.
        System.out.println("hash code for str1: " + str1.hashCode());
        System.out.println("hash code for str2: " + str2.hashCode() + "\n");

        // Hash codes are different for different MyClass objects.
        System.out.println("hash code for MyClass obj1: " + obj1.hashCode());
        System.out.println("hash code for MyClass obj2: " + obj2.hashCode()+"\n");

        // Method equals() overridden in the String class.
        System.out.println("str1.equals(str2): " + str1.equals(str2));
        System.out.println("str1 == str2 : " + (str1 == str2) + "\n");

        // Method equals() from the Object class called.
        System.out.println("obj1.equals(obj2): " + obj1.equals(obj2));
        System.out.println("obj1 == obj2 : " + (obj1 == obj2) + "\n");

        // The runtime object that represents the class of an object.
        Class rtStringClass  = str1.getClass();
        Class rtMyClassClass = obj1.getClass();
        // The name of the class represented by the runtime object.
        System.out.println("Class for str1: " + rtStringClass);
        System.out.println("Class for obj1: " + rtMyClassClass + "\n");
        // The toString() method is overridden in the String class.
        String textRepStr = str1.toString();
        String textRepObj = obj1.toString();
        System.out.println("Text representation of str1: " + textRepStr);
        System.out.println("Text representation of obj1: " + textRepObj + "\n");

        // Shallow copying of arrays.
        MyClass[] array1 = {new MyClass(), new MyClass(), new MyClass()};
        MyClass[] array2 = (MyClass[]) array1.clone(); // Cast required.
        // Array objects are different, but share the element objects.
        System.out.println("array1 == array2 : " + (array1 == array2));
        for(int i = 0; i < array1.length; i++) {
            System.out.println("array1[" + i + "] == array2[" + i + "] : "
                       + (array1[i] == array2[i]));

        // Clone an object of MyClass.
        MyClass obj3 = (MyClass) obj1.clone();
        System.out.println("hash code for MyClass obj3: " + obj3.hashCode());
        System.out.println("obj1 == obj3 : " + (obj1 == obj3));

class MyClass implements Cloneable {

    public Object clone() {
        Object obj = null;
        try { obj = super.clone();}        // Calls overridden method.
        catch (CloneNotSupportedException e) { System.out.println(e);}
        return obj;

Output from the program:

hash code for str1: -1704812257
hash code for str2: -1704812257

hash code for MyClass obj1: 24216257
hash code for MyClass obj2: 20929799

str1.equals(str2): true
str1 == str2 : false

obj1.equals(obj2): false
obj1 == obj2 : false

Class for str1: class java.lang.String
Class for obj1: class MyClass

Text representation of str1: WhoAmI
Text representation of obj1: MyClass@17182c1
array1 == array2 : false
array1[0] == array2[0] : true
array1[1] == array2[1] : true
array1[2] == array2[2] : true

hash code for MyClass obj3: 16032330
obj1 == obj3 : false