Using Java’s Reflection API: Part I

When looking at the “current” generation of high level languages, a common trend is to move from strictly compiled languages (such as C) to interpreted, platform-independent languages (such as PHP or Java). However, many people do not fully use or appreciate the additional language features that are available in interpreted languages. In many ways, Java appears to be a compiled language—there are Java source files, and there are Java object files. One is edited by the user, and one is executed by the virtual machine as is—there is no additional output file created.

(Un)fortunately, this is not the case. The Java compiled .class files are more akin to tokenized versions of the source file, which can then be executed by an interpreter without additional parsing. The fundamental difference is that the files are interpreted by another program, rather than executed directly by the processor. This means that a lot of additional information can be (and is) loaded into the interpreter, and is made available to the program as it is running.

But, how does one access that information? The Reflection API was created specifically for this purpose. It gives runtime insight into the structure and capabilities of classes without requiring any explicit information to be given in the source code. For example, let’s say you are designing a framework for deploying applications with customizable components, and you wish to allow 3rd parties to develop and release components completely independently of your framework. How can you create an instance of a class that you don’t have the source code for?

The answer is simple: Use the class loader to create a Class object representing the class that is being loaded. Then, use reflection to obtain a reference to the constructor for that class, and then use that constructor to create a specific instance and return it:

/**
  * First, default constructors without arguments.
  */
public static Object createClass(String name) throws Exception {
	Class c = Class.forName(name);
	return c.newInstance();
}
/**
 * Then, specific constructors for the series of arguments
 */
public static Object createClass(String name, Object[] args, Class types[]) throws Exception {
	Class c = Class.forName(name);
	Constructor constructor = (Constructor)c.getConstructor(types);
	return constructor.newInstance(args);
}

Here, it is possible to infer the types of the parameters by constructing an array of the Class objects returned by getClass(), when called for each argument, but I felt that it would be better to make this piece of sample code slightly cleaner (although less useful than if the types are inferred automatically, another use of Reflection). Next time, I’ll post a sample that uses reflection invisibly, because it is ultimately far easier for the programmer if library code requires less effort to use and provides more functionality.

Given a fully qualified binary class name (which can be read out of a configuration file, for instance), it is possible to load a class and create an instance of it without ever knowing its name at compile time. This notion of looking up a constructor at runtime can be extended to looking up any method or field that belongs to a class as well, which enables one to make static calls to functions on unknown classes. This is, in general, not particularly safe, but if one defines an abstract base class with a series of static methods with “default” implementations, and then a child class that overrides one or more of the static methods, it is possible to use reflection to obtain references to the appropriate static method as another form of delayed static binding:

package articles;

import java.lang.reflect.*;

public class LSB {

	/**
	 * Two simple classes to demonstrate how late static binding
	 * can be done. The third does not override the method.
	 */
	public static class A {
		public static void test() {
			System.out.println("This is A.");
		}
	}
	public static class B extends A {
		public static void test() {
			System.out.println("But this is B.");
		}
	}
	public static class C extends A {
		// Does not override A's test(), so it should be called.
	}

	/**
	 * Your compiler may complain about the null pointers, but if you take its advice
	 * and cast them, it WILL NOT WORK, because they are treated differently when cast.
	 */
	public static void staticCall(String className, String m) throws Exception {
		Class c = Class.forName(className);
		Method method = c.getMethod(m, null);
		method.invoke(null, null);
	}

	/**
	 * Inner classes are referenced in a very strange way, which makes
	 * this less than pretty.
	 */
	public static void main(String[] args) throws Exception {
		staticCall("articles.LSB$A", "test");
		staticCall("articles.LSB$B", "test");
		staticCall("articles.LSB$C", "test");
	}

}

In this example, all of the static methods must not take any parameters, and their return values are discarded if not void. This can, however, be modified, but I’ll leave that for another day.

Lots of people love patterns, so I’ll mention here how Reflection can be integrated with existing patterns to increase functionality and applicability while decreasing the complexity of the code. By combining the concept of dynamic construction with delayed static lookups, it is possible to reinvent the Factory pattern (among others) by combining it with the Strategy pattern. Each object is now expected to understand how to construct itself, so when an object is to be created, its full class is determined, and then the factory passes creation off to a specific, static method create() (or similar), which then builds the object and passes it back. In the next part of this series, I’ll show how to implement such a factory, and I’ll show how to address some of the limitations of the factory pattern by using dynamic constructor calls within the factory methods.

Posted in Uncategorized.

Tagged with , .


One Response

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Continuing the Discussion

  1. Using Java’s Reflection API: Part II – Authoritative Opinion linked to this post on June 10, 2009

    [...] Last time I gave a brief overview of some of the Reflection utilities available in Java, with the promise to discuss how to rethink a common design pattern using the capabilities of reflection: the Factory Pattern. The brief wiki article I linked lists three main limitations: [...]



Some HTML is OK

or, reply to this post via trackback.