Previous | Next | Trail Map | Learning the Java Language | More Features of the Java Language


Being a Descendent of Object

The Object(in the API reference documentation) class sits at the top of the class hierarchy tree in the Java platform. Every class in the Java system is a descendent, direct or indirect, of the Object class. This class defines the basic state and behavior that all objects must have, such as the ability to compare oneself to another object, to convert to a string, to wait on a condition variable, to notify other objects that a condition variable has changed, and to return the class of the object.

Your classes may want to override the following Object methods:

Your class cannot override these Object methods (they are final):

The clone Method

You use the clone method to create objects from other objects of the same type. By default, objects are not cloneable, so Object's implementation of this method throws a CloneNotSupportedException. If you want your class to be cloneable, you must implement the Cloneable interface and override this method.

Your version of the clone method must provide for a field-by-field copy of the object being cloned. Here's a partial listing of a new version of the Stack class that implements the Cloneable interface and overrides the clone method (changes are indicated with a change in font):

public class Stack implements Cloneable
{
    private Vector items;

    // code for Stack's methods and constructor not shown

    protected Object Clone() {
        try {
            Stack s = (Stack)super.clone();
            s.items = (Vector)items.clone();
            return s;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen because Stack is Cloneable
            throw new InternalError();
        }
    }
}
The implementation for Stack's clone method is relatively simple because it can call Object's implementation of the clone method. Also, the only member of Stack, a Vector, is also cloneable. Be careful: clone should not use new to create the clone and should not call constructors.

The equals Method

You use the equals method to compare two objects for equality. This method returns true if the objects are equal, false otherwise. Note that equality does not necessarily mean that the objects are the same object. Consider this code that tests two Integers, one and anotherOne, for equality:
Integer one = new Integer(1), anotherOne = new Integer(1);

if (one.equals(anotherOne))
    System.out.println("objects are equal");
This program displays objects are equal even though one and anotherOne reference two distinct objects. They are considered equal because they contain the same integer value.

Your classes should override the equals method to provide an appropriate equality test. Your equals method should compare the contents of the objects to see if they are functionally equivalent and return true if they are.

The finalize Method

The Object class provides a method, finalize, that cleans up an object before it is garbage collected. This method's role during garbage collection was discussed previously in Cleaning Up Unused Objects. Also, Writing a finalize Method showed you how to override the finalize method to handle the finalization needs for your classes.

The toString Method

Object's toString method returns a String representation of the object. You can use toString along with System.out.println to display a text representation of an object, such as the current thread:
System.out.println(Thread.currentThread().toString());
The String representation for an object depends entirely on the object. The String representation of an Integer object is the integer value displayed as text. The String representation of a Thread object contains various attributes about the thread, such as its name and priority. For example, the previous line of code displays the following output:
Thread[main,5,main]
The toString method is very useful for debugging. It behooves you to override this method in all your classes.

The getClass Method

The getClass method is a final method that returns a runtime representation of the class of this object. This method returns a Class object. You can query the Class object for various information about the class, such as its name, its superclass, and the names of the interfaces that it implements. The following method gets and displays the class name of an object:
void PrintClassName(Object obj) {
    System.out.println("The Object's class is " + obj.getClass().getName());
}
One handy use of the getClass method is to create a new instance of a class without knowing what the class is at compile time. The following sample method creates a new instance of the same class as obj, which can be any class that inherits from Object (which means that it could be any class):
Object createNewInstanceOf(Object obj) {
    return obj.getClass().newInstance();
}


Note: You also can get a Class object from a class name using a class literal. For example, to get the Class object for the String class use String.class. This is equivalent to, but more efficient than, calling Class.forName(String).

The notify, notifyAll, and wait Methods

You cannot override Object's notify and notifyAll methods and its three versions of wait. This is because they are critical for ensuring that threads are synchronized. The use of these methods is covered in Doing Two or More Tasks at Once: Threads(in the Writing Java Programs trail). Take particular note of the section titled Synchronizing Threads(in the Writing Java Programs trail).


Previous | Next | Trail Map | Learning the Java Language | More Features of the Java Language