Bruce Eckel's Thinking in Java Contents | Prev | Next

RTTI syntax

Java performs its RTTI using the Class object, even if you’re doing something like a cast. The class Class also has a number of other ways you can use RTTI.

First, you must get a handle to the appropriate Class object. One way to do this, as shown in the previous example, is to use a string and the Class.forName( ) method. This is convenient because you don’t need an object of that type in order to get the Class handle. However, if you do already have an object of the type you’re interested in, you can fetch the Class handle by calling a method that’s part of the Object root class: getClass( ). This returns the Class handle representing the actual type of the object. Class has several interesting and sometimes useful methods, demonstrated in the following example:

//: ToyTest.java
// Testing class Class

interface HasBatteries {}
interface Waterproof {}
interface ShootsThings {}
class Toy {
  // Comment out the following default
  // constructor to see 
  // NoSuchMethodError from (*1*)
  Toy() {} 
  Toy(int i) {} 
}

class FancyToy extends Toy 
    implements HasBatteries, 
      Waterproof, ShootsThings {
  FancyToy() { super(1); }
}

public class ToyTest {
  public static void main(String[] args) {
    Class c = null;
    try {
      c = Class.forName("FancyToy");
    } catch(ClassNotFoundException e) {}
    printInfo(c);
    Class[] faces = c.getInterfaces();
    for(int i = 0; i < faces.length; i++)
      printInfo(faces[i]);
    Class cy = c.getSuperclass();
    Object o = null;
    try {
      // Requires default constructor:
      o = cy.newInstance(); // (*1*)
    } catch(InstantiationException e) {}
      catch(IllegalAccessException e) {}
    printInfo(o.getClass());
  }
  static void printInfo(Class cc) {
    System.out.println(
      "Class name: " + cc.getName() +
      " is interface? [" +
      cc.isInterface() + "]");
  }
} ///:~ 

You can see that class FancyToy is quite complicated, since it inherits from Toy and implements the interfaces of HasBatteries, Waterproof, and ShootsThings. In main( ), a Class handle is created and initialized to the FancyToy Class using forName( ) inside an appropriate try block.

The Class.getInterfaces( ) method returns an array of Class objects representing the interfaces that are contained in the Class object of interest.

If you have a Class object you can also ask it for its direct base class using getSuperclass( ). This, of course, returns a Class handle that you can further query. This means that, at run time, you can discover an object’s entire class hierarchy.

The newInstance( ) method of Class can, at first, seem like just another way to clone( ) an object. However, you can create a new object with newInstance( ) without an existing object, as seen here, because there is no Toy object, only cy, which is a handle to y’s Class object. This is a way to implement a “virtual constructor,” which allows you to say “I don’t know exactly what type you are, but create yourself properly anyway.” In the example above, cy is just a Class handle with no further type information known at compile time. And when you create a new instance, you get back an Object handle. But that handle is pointing to a Toy object. Of course, before you can send any messages other than those accepted by Object, you have to investigate it a bit and do some casting. In addition, the class that’s being created with newInstance( ) must have a default constructor. There’s no way to use newInstance( ) to create objects that have non-default constructors, so this can be a bit limiting in Java 1. However, the reflection API in Java 1.1 (discussed in the next section) allows you to dynamically use any constructor in a class.

The final method in the listing is printInfo( ), which takes a Class handle and gets its name with getName( ), and finds out whether it’s an interface with isInterface( ).

The output from this program is:

Class name: FancyToy is interface? [false]
Class name: HasBatteries is interface? [true]
Class name: Waterproof is interface? [true]
Class name: ShootsThings is interface? [true]
Class name: Toy is interface? [false] 

Thus, with the Class object you can find out just about everything you want to know about an object.

Contents | Prev | Next