The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Learning the Java Language
Lesson: More Features of the Java Language

## Being a Descendent of Object

> The `Object` 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. The `equals`/`hashCode` are listed together as they must be overridden together.

> - `clone`
> - `equals`/`hashCode`
> - `finalize`
> - `toString`
> Your class cannot override these `Object` methods (they are final):
> - `getClass`
> - `notify`
> - `notifyAll`
> - `wait`

### The `clone` Method

> You use the `clone` method to create an object from an existing object. To create a clone, you write:

> >     aCloneableObject.clone();

> `Object`'s implementation of this method checks to see if the object on which `clone` was invoked implements the `Cloneable` interface, and throws a `CloneNotSupportedException` if it does not. Note that `Object` itself does not implement `Cloneable`, so subclasses of `Object` that don't explicitly implement the interface are not cloneable.

> If the object on which `clone` was invoked does implement the `Cloneable` interface, `Object`'s implementation of the `clone` method creates an object of the same type as the original object and initializes the new object's member variables to have the same values as the original object's corresponding member variables.

> The simplest way to make your class cloneable then, is to add implements Cloneable to your class's declaration. For some classes the default behavior of `Object`'s `clone` method works just fine. Other classes need to override `clone` to get correct behavior.

> Consider the `Stack` class, which contains a member variable that refers to a `Vector`. If `Stack` relies on `Object`'s implementation of `clone`, then the original stack and its clone will refer to the same vector. Changing one stack will change the other, which is undesirable behavior.

> Here then is an appropriate implementation of `clone` for our `Stack` class, which clones the vector to ensure that the original stack and its clone do not refer to the same vector (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();	// clone the stack
> >                 s.items = (Vector)items.clone();	// clone the vector
> >                 return s;				// return the clone
> >             } catch (CloneNotSupportedException e) {
> >                 // this shouldn't happen because Stack is Cloneable
> >                 throw new InternalError();
> >             }
> >         }
> >     }

> The implementation for `Stack`'s `clone` method is relatively simple: It calls `super.clone`, which `Stack` inherits from `Object` and which creates and initializes an instance of the correct type. At this point, the original stack and its clone refer to the same vector. Next the method clones the vector.

> Be careful: `clone` should never use `new` to create the clone and should not call constructors. Instead, the method should call `super.clone`, which creates an object of the correct type and allows the hierarchy of superclasses to perform the copying necessary to get a proper clone.

### The `equals` and `hashCode` Methods

> You must override the `equals` and `hashCode` methods together.

> The `equals` method compares two objects for equality and returns `true` if they are equal. The `equals` method provided in the `Object` class uses the identity function to determine if objects are equal (if the objects compared are the exact same object the method returns `true`).

> However, for some classes, two distinct objects of that type might be considered equal if they contain the same information. Consider this code that tests two `Integer`s, `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 the objects compared contain the same integer value.

> Your classes should only override the `equals` method if the identity function is not appropriate for your class. If you override `equals`, then override `hashCode` as well.

> The value returned by `hashCode` is an `int` that maps an object into a bucket in a hash table. An object must always produce the same hash code. However, objects can share hash codes (they aren't necessarily unique). Writing a "correct" hashing function is easy--always return the same hash code for the same object. Writing an "efficient" hashing function, one that provides a sufficient distribution of objects over the buckets, is difficult and is out of the scope of the tutorial.

> Even so, the hashing function for some classes is relatively obvious. For example, an obvious hash code for an `Integer` object is its integer value. For an example of a class that overrides the `equals` and `hashCode` methods, see the `BingoBall` class in BINGO!.

### 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. The `finalize` method is called automatically by the system and most classes you write do not need to override it. So you can generally ignore this method.

### 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 an object. This method returns a `Class` object.

> Once you have a `Class` object you can query it 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 a `Class` object 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: . Take particular note of the section titled Synchronizing Threads.

> | Start of Tutorial > Start of Trail > Start of Lesson | Search