Most of the following chapters will end with a brief listing of one of the standard built-in classes. You should just scan the list, look at the typical methods, and then go on. Later when you want to refer to the class in detail, you can look back at the end of the chapters.
We've mentioned a couple of times that there is a class called "Object" that is the ultimate superclass (parent class) of all other classes in the system. The members that exist in Object are thus inherited by every class in the system. Whatever class you have, an instance of it can call any of these methods. Here is what Object has:
public class Object { public java.lang.Object(); public java.lang.String toString(); protected native java.lang.Object clone() throws CloneNotSupportedException; public boolean equals(java.lang.Object); public native int hashCode(); protected void finalize() throws Throwable; public final native java.lang.Class getClass(); // methods relating to thread synchronization public final native void notify(); public final native void notifyAll(); public final void wait() throws InterruptedException; public final native void wait(long) throws InterruptedException; public final void wait(long, int) throws InterruptedException; }
The "throws SomeException" clause is an announcement of the kind of unexpected error return that the method might give you.
There are several variations on the standard OS synchronization primitives wait() and notify(). These are described in the chapter on Threads. The remaining methods in Object, and thus in every class, are further highlighted below.
In each case, the method offers some useful, though somewhat elementary, functionality. Programmers are supposed to provide their own version of any of these methods to replace the basic one, if necessary. When an object (any object) calls a method, its own version of that method is preferred, over an identically-named method in a parent class, as we'll see in the second chapter on OOP.
public java.lang.String toString();
This is a very handy method! You can call it explicitly and it will return a string that "textually represents" this object. Use it while doing low-level debugging to see if your objects really are what you thought they were. Here's what I get for Fruit:
public class Fruit { int grams; int cals_per_gram; public static void main (String args[]) { Fruit f = new Fruit(); System.out.println( " f = " + f.toString() ); } }
When you run the program, the output is as follows:
f = Fruit@a04c8d82
It is also invoked implicitly when any object and a String object are joined in a "+" operation. That operation is defined as String concatenation. To turn the other object into a String, its toString() method is called. It constitutes a piece of "magic" extra operator support for type String.
protected native Object clone() throws CloneNotSupportedException
The "native" keyword says that the body of this method is not written in Java, but will be provided in a native library linked in with the program.
Java supports the notion of cloning, meaning to get a complete bit-for-bit copy of an object. Java does a shallow clone, meaning that when an object has data fields that are other objects, it simply copies the reference. The alternative is to recursively clone all referenced classes, too, known as a deep clone.
As a programmer, you can choose the exact cloning behavior you want. If a class wants to support deep cloning on its objects, it can provide its own version of clone(). When you provide your own version of clone, you can also change the access modifier to public (so other classes can call it and hence clone this object) rather than the default protected (outside this package, only subclasses can clone).
Note that clone() returns an Object. The object returned by clone() is usually immediately cast (type converted) to the correct type, as in this example:
Vector v = new Vector(); Vector v2; v2 = (Vector) v.clone(); // cast it back to Vector type
Not every class should support the ability to clone. If I have a class that represents unique objects, such as employees in a company, the operation of cloning doesn't make sense. Since methods in Object are inherited by all classes, the system places a further requirement on classes that want to be cloneablethey need to implement the cloneable interface to indicate that cloning is valid for them. Implementing an interface is described later.
public boolean equals(Object obj)
The method does a comparison of reference types, such as:
if (obj1.equals(obj2) ) ...
This is equivalent to the following:
if (obj1 == obj2 ) ...
The point is that you can provide your own version of equals() to give it whatever semantics make sense for your class. This has been done for String, because two Strings are usually considered equal if they contain the exact same sequence of characters, even if they are different objects. When you override equals(), you'll want to override hashCode() to make certain equal Objects get the same hashcode.
public native int hashCode ()
A hashcode is a value that uniquely identifies an individual object. For example, you could use the memory address of an object as its hashcode if you wanted. It's used as a key in the standard java.util.Hashtable class. We'll say more about hashtables later.
protected void finalize() throws Throwable
The method finalize() is a hook you can override to help with memory management. For more information, see the chapter on garbage collection. That "throws Throwable" is an indication of what error conditions (exceptions) this method can potentially raise. For more on this topic, see the chapter on exceptions.
public final native Class getClass()
Java maintains a runtime representation for all classes, known as Run Time Type Identification or RTTI. This method gets that information, which is of type Class. The class whose name is Class has several methods to tell you more about the class to which an arbitrary object belongs. You invoke the getClass method in the usual way:
Class whatAmI = myobject.getClass();
Having seen our first reasonable Java program, in the next chapter we'll look at the small building blocks of individual tokens that the compiler sees.