The Class Whose Name Is Class

Here's where the terminology admittedly can get a little confusing. We saw a few pages back that every object has some Run Time Type Information associated with it. The RTTI for any object is stored in an object whose class is called “Class.” Class could certainly use a better, less self-referential name, like ClassInformation or just RTTI.

A big use of Class is to help with loading new classes during program execution. A lot of other languages load an entire program before they start execution. Java encourages dynamic loading. Classes only need to be loaded on demand when they are first referenced.

When you compile a class called, say, Fruit, the compiler creates the bytecode file Fruit.class. When the first reference to a Fruit type or object is encountered at run-time, the JVM asks the java.lang.ClassLoader class to find and load that class file. Typically, the ClassLoader transforms the fully qualified name into a file name and looks for that in certain places locally (and for applets, it looks across the net back to the server). It will look in the directories on the class path; it will look in the libext directory in the run-time library; it will look at any jar files you have named, and so on. If the class file is not found, an error is reported. Otherwise the JVM loads the bytecode instructions into memory and automatically creates a Class object to represent the class.

Class provides the information for checking casts at run-time, and it also lets a program introspect all the members of a class—the data fields and the methods. These are systems programming activities, unlikely to occur in your programs, but providing Class makes it easy to program them without stepping outside the Java system. You can safely skim over the rest of this section and return when you have a specific need to look at RTTI.

To access the run-time type information for a class, you need an object of type Class. You can get one in three ways. Here's some code showing the alternatives:

Object o = new Timestamp();

Class which = o.getClass(); // getClass is a method in Object

or

Class which = Class.forName("Timestamp"); // forName is a static method

or

Class which = Timestamp.class; // class literal

The second alternative will throw a ClassNotFoundException if no class of that name can be found, so if you are experimenting with this code, you'll need to put that statement in a try/catch clause described in the Exceptions chapter.

The last alternative is called a class literal. You can jam the characters .class onto the end of any type at all, even a primitive type like int, and it gets you the Class RTTI associated with the type. You'll choose which of the alternatives to use depending on whether you have an object, the classname in a String, or the class.

Once you have the class object you can invoke its methods. The strict left-to-right evaluation of Java allows method calls to be chained together in one statement. You can do this with any methods where the result of one method is the reference used in the next:

String name = myobject.getClass().getName();

Method getName() returns a String containing the name of the class, e.g. “java.awt.Window” or “Timestamp”.

The class whose name is Class looks like this in JDK 1.4. The JDK 1.5 version has been retrofitted to give it a generic parameter. Instantiations now specify the type for which they are a Class object. Chapter 15 has the full story.

public final class java.lang.Class  {
     public java.io.InputStream getResourceAsStream(java.lang.String);
     public java.net.URL getResource(java.lang.String);

     public native String getName();
     public static native java.lang.Class forName(java.lang.String);
     public native java.lang.Object newInstance();

     static native Class getPrimitiveClass(java.lang.String);

     public native boolean isInstance(java.lang.Object);
     public native boolean isAssignableFrom(java.lang.Class);
     public native boolean isInterface();
     public native boolean isArray();
     public native boolean isPrimitive();

// security related
     public native ClassLoader getClassLoader();
     public native Object getSigners()[];
     native void setSigners(java.lang.Object[]);

// introspection on the class, its ancestors, members and constructors
     public native Class getSuperclass();
     public native Class getInterfaces()[];
     public native Class getComponentType();
     public native int getModifiers();
     public Class getDeclaringClass();
     public Class getDeclaredClasses()[];
     public Class getClasses()[];
     public reflect.Constructor getConstructors()[];
     public reflect.Constructor getConstructor(java.lang.Class[]);
     public reflect.Constructor getDeclaredConstructors()[];
     public reflect.Constructor getDeclaredConstructor(java.lang.Class[]);

     public reflect.Field getFields()[];
     public reflect.Field getField(java.lang.String);
     public reflect.Field getDeclaredFields()[];
     public reflect.Field getDeclaredField(java.lang.String);

     public reflect.Method getMethods()[];
     public reflect.Method getMethod(java.lang.String, java.lang.Class[]);
     public reflect.Method getDeclaredMethods()[];
     public reflect.Method getDeclaredMethod(
                              java.lang.String, java.lang.Class[]);

     public java.lang.String toString();
}

A description of some methods of Class follow. We've already covered the method that returns the name of the Class.

public native String getName();

This next example is a surprising method—it allows you to create an object of the class for which this is the RTTI. Coupled with the forName() method, this lets you create an object of any class whose name you have in a String. Highly dynamic! The no-arg constructor of the appropriate class is called, so it better have one.

public native Object newInstance()
          throws InstantiationException, IllegalAccessException

In the following example, if you have an instance of a class, and you cast it to the class that you know it is, you can call its methods:

String s = "java.awt.Window";
Object f = Class.forName(s).newInstance();

java.awt.Component c = (java.awt.Window) f;
c.setVisible(true);

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.51.228