Dabbling in Reflection

Jul 7, 2014, 3:00 PM

Tags: java

In a similar vein to my post from the other day, I'd like to discuss one of the other bugaboos that crops up from time to time in the edges of XPages development, usually spoken of in hushed tones: reflection.

If you're not familiar with the term, reflection is an aspect of metaprogramming; specifically, it's the ability to inspect and operate on objects and classes at runtime. Reflection in Java isn't as smooth as it is in other languages, but it makes sense as you work with it.

The most basic form is the getClass() that every non-null object has: you can use it to get an object representing the class of the object in question, which is your main starting point. This code will print out "java.lang.String":

Class<?> stringClass = "".getClass();

From here, you can start to get fancier. For example, this code...

Class<?> stringClass = "".getClass();

for(java.lang.reflect.Method method : stringClass.getMethods()) {

... will print out the signatures for all public instance and static methods, with output like:

public boolean java.lang.String.equals(java.lang.Object)
public int java.lang.String.hashCode()
public java.lang.String java.lang.String.toString()
public char java.lang.String.charAt(int)
public int java.lang.String.compareTo(java.lang.String)
public int java.lang.String.compareTo(java.lang.Object)
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

There is also a variant to show just the methods from that specific class, including private/protected ones. But the java.lang.reflect.Method objects you get there are useful for more than just printing out signatures: they're proxies for actually executing the method against an appropriate object. To demonstrate, say you have this class:

public class ExampleClass {
	private String name;

	public ExampleClass(final String name) { this.name = name; }

	public void printName() { System.out.println(name); }

You can then use reflection to call the method (this also demonstrates an alternate way of getting a class object if you know the class you want):

ExampleClass someObject = new ExampleClass("my name is someObject");
Method printNameMethod = ExampleClass.class.getMethod("printName");

So, okay, I found a way to call a method that involves way more typing for no gain - so what? Well, in a situation where reflection is actually useful, you won't actually know what methods are available. And this happens constantly in XPages, but you don't have to worry about it: reflection is how EL and SSJS do their work. If you've ever looked through one of the monstrous stack traces emitted by an XPage with an exception, you've probably seen this very call:

    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

That's reflection in action. The EL resolver found the object and then used reflection to determine how it should get the "output" property (most likely the instanceof operator) and then, determining that it was talking to a plain bean, constructed the name "getOutput", asked the object's class for that method, and invoked it.

Like most things in Java, reflection gets more complicated and powerful from here; there are facilities for dealing with generic types, creating new instances, reading annotations, making private properties/methods accessible, and so forth. But the basics are simple and worth knowing: it's all about asking an object what it is and what it is capable of. Once you're comfortable with that, the rest of the pieces will fall into place as you encounter them.

Commenter Photo

Don Mottolo - Jul 8, 2014, 1:07 PM

Thanks for posting this info.  Reflection is one of those concepts I'm vaguely aware of, but this explanation is helpful.  (Just want to let you know, it is appreciated.)

Commenter Photo

Jesse Gallagher - Jul 8, 2014, 1:13 PM

Glad to hear it! And that's the impetus for the post: I figured there are a lot of people who are familiar by name with things like reflection, but haven't had the opportunity to learn more or why they're useful.

New Comment