Software Design (CS223 2004F)

Introspection in Java

Summary: This document provides a short introduction to the idea of introspection and the ways in which one can take advantage of introspection in Java.

Contents:

Useful Javadoc:

The Basics

When humans introspect, they look inside themselves. When our programs introspect, they also look inside themselves, but in a different way. In object-oriented languages, introspection is the idea that program code can get information on itself. In object-oriented languages, introspection permits programs to get and use information on classes and objects at run-time. Using introspection, one can ask an object for its class, ask a class for its methods and constructors, find out the details of those methods and constructors, and tell those methods to execute.

Introspection in Java also reflects the idea that everything is or can be an object. In particular, you can have objects of type Class and objects of type Method.

Important Classes and Methods

At the center of Java introspection is the java.lang.Class class. You can obtain a Class object in a variety of ways. The two most common are the getClass() method provided by Object and the static Class.forName(String name) method.

Once you have a class, you can get a variety of information, including its name, its fields, its constructors, its methods, and its package. Most often, we focus on the methods and constructors of the class. We can get an array of all constructors with getConstructors() and a particular constructor with getConstructor(Class[] params). Similarly, you can get all methods with getMethods() and a particular method with getMethod(String name, Class[] params). If you're worried primarily about the methods and constructors declared within a particular class, you can use getDeclaredMethods.

These methods return objects in the java.lang.reflect.Constructor and java.lang.reflect.Method classes, respectively. The central method in Constructor is newInstance(Object[] params). The central method in Method is invoke(Object arg, Object[] params).

An Example: Obfuscating a Method Call

Consider the relatively simple method call

   foo.bar("Baz", 42);

Using introspection, we could express that approximately as

foo.getClass().getMethod(
                "bar",
                new Class[] {
                        Class.forName("java.lang.String"),
                        Integer.TYPE }).
        invoke(foo, new Object[] {
                "Baz",
                new Integer(42) });

Other than obfuscation and verbosity, the main disadvantage of the second version is that it takes compile-time checking (e.g., that there is a method named "bar") and turns it into run-time checking. Some might consider that an advantage.

An Example: Summarizing a Class

Here's a simple example of the use of introspection to print a summary of the methods in a class.

  public static void summarize(String className)
    throws Exception
  {
    Class c = Class.forName(className);
    System.out.println("Class: " + c.getName());
    Method[] methods = c.getMethods();
    System.out.println("  Methods: ");
    for (int i = 0; i < methods.length; i++) {
      System.out.print("    " + methods[i].toString());
      if (methods[i].getDeclaringClass() != c)
        System.out.println(" (inherited from "
          + methods[i].getDeclaringClass().getName()
          + ")");
      else
        System.out.println();
    }
  } // summarize(String)

Some Applications

Introspection has a wide variety of applications. One of its most important applications is in writing applications that support plug-ins. Introspection allows the main application to examine each of its plug-ins for the methods it supports and then call them when appropriate. Without introspection, it could not determine the names and parameter types of those methods.

JUnit also makes clever use of introspection. In particular, it uses introspection to identify all the zero-ary methods in a test suite that begin with the word "test". It then calls each of those methods in order.

Introspection is also helpful for a variety of networked applications and I believe it is central to the JavaBeans technology.

We could write an alternative to Javadoc using introspection, and I expect that Javadoc uses introspection.

Some Confusing Issues

What is the class of a primitive type, such int?
Use the TYPE constant in the corresponding class. For example, the class of int is Integer.TYPE.
Given that parameters are supposed to be arrays of objects, what should I do when I want to pass a primitive type, such as an int?
Build an object of the corresponding class (e.g., Integer for int, Double for double, Boolean for bool).

 

History

Thursday, 4 November 2004 [Samuel A. Rebelsky]

 

Disclaimer: I usually create these pages on the fly, which means that I rarely proofread them and they may contain bad grammar and incorrect details. It also means that I tend to update them regularly (see the history for more details). Feel free to contact me with any suggestions for changes.

This document was generated by Siteweaver on Tue Dec 7 21:49:33 2004.
The source to the document was last modified on Thu Nov 4 10:51:40 2004.
This document may be found at http://www.cs.grinnell.edu/~rebelsky/Courses/CS223/2004F/Handouts/introspection.html.

You may wish to validate this document's HTML ; Valid CSS! ; Check with Bobby

Samuel A. Rebelsky, rebelsky@grinnell.edu