CS102: Run-Time Type Identification, Reflection

Copyright © 1999, Kenneth J. Goldman

Reflection

Lately, we've spent a lot of time on how processes communicate externally to send and receive data. But what happens when the data being sent is not just a primitive or an object whose type is known by the receiving process. In other words, what happens if we receive an object but don't know anything about it -- what instance variables and methods it has, etc.


Another way to pose the question: What can we find out about the type of an object at run-time?


So far, we've seen one construct supporting this: instanceof, the operator that lets you test at run-time, whether or not an object is of a given type. However, it turns out that the java.lang.reflect package lets you find out almost anything you want to know about an object's class at run-time.


The first thing to observe is that Java provides a
class Class
Isn't this recursive? What's the deal? Actually it's fairly straightforward...


Each instance of the class Class encapsulates the information about a particular class or interface. There is one such object for each class or interface loaded into the JVM.


There are two ways to get an instance of class Class from within a running program:


  1. Ask for it by name using the static method forName:
    Class fooClass = Class.forName("Foo");
    This method will return the Class object that describes the class Foo


  2. Ask an instance of any Object for its class:
    Foo f = new Foo();
    Class fooClass = f.getClass();

Question: Is this legal?
Class classClass = Class.forName("Class");
Yes! You get back the instance of Class that describes the class Class.


Once you have a Class object, what can you do with it? You can call methods on it to find out information about the class. None of the methods are mutators, so you can't change the class at run-time. However, you can use it to create new instance of a class, and to call methods on any instance.


Some of the methods available in class Class are:


Constructor getConstructor(Class[] paramTypes);
Constructor[] getConstructors();

Field getField(String name);
Field[] getFields();

Method getMethod(String name, Class[] paramTypes);
Method[] getMethods();

boolean isInstance(Object obj);
boolean isPrimitive();

String getName();
String toString();

The return types Constructor, Field, and Method are defined in Package java.lang.reflect.


To see how to use these, take a look at the ReflectionExample.java.