Java Reflection makes it easy to find fields, methods, and constructors in your Java classes. Most of the time a single class is all you need to look at. However, sometimes you need to navigate through a class hierarchy.
In this post, I’ll show you how to use Java Reflection to navigate class hierarchies. You’ll learn two techniques to do this, so you can pick the one that best suits your needs.
We’ll need an example to work with, so let’s use the Java Swing TextField
class. Here’s the class hierarchy for JTextField
from the Java API documentation.
Class JTextField
java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.text.JTextComponent javax.swing.JTextField
You can see that this class hierarchy is fairly deep. The Object
class is at the top and JTextField
is at the bottom. The other classes in between fill in the complete inheritance hierarchy.
Let’s write a Java Reflection program to navigate through this class hierarchy and print out the class and package names. We’ll write this program specifically for the JTextField
class, but you should be able to easily adapt it to access class names in the inheritance hierarchy of any Java class.
Our program needs the getSuperclass()
and getName()
methods from the Java Reflection API. Both methods are called with Class<?>
objects.
The getName()
method returns a string representing the Class<?>
object’s package and class name. The getSuperclass()
method returns a Class<?>
object representing the parent or super class of the invoking Class<?>
object. Note that getSuperclass()
returns null when called with a Class<?>
object representing the Object
class, since Object
has no parent.
Recursive Approach
Here’s the first technique for navigating class hierarchies.
public class SuperClasses { public static void main(String[] args) { showHierarchy(JTextField.class); } static void showHierarchy(Class<?> c) { if (c.getSuperclass() == null) { System.out.println(c.getName()); return; } showHierarchy(c.getSuperclass()); System.out.println(c.getName()); } }
Interestingly, the showHierarchy()
method has no loop as it navigates through the JTextField
hierarchy. That’s because showHierarchy()
is recursive. Do you see how this works?
Each call to showHierarchy()
first invokes c.getSuperclass()
at line 6 to fetch the parent of the current class. If this method does not return null, a recursive call to showHierarchy()
is invoked with this parent class at line 10. Each recursion nests stack frames as it works its way up the inheritance tree.
What makes the recursion finally stop? When we reach the Object
class in the hierarchy, c.getSuperclass()
returns null and the if
statement at line 6 is true. At this point, the method calls c.getName()
at line 7 to print the Object
class before returning.
Next, each recursive invocation of showHierarchy()
at line 10 returns as the nested stack frames unwind. This makes showHierarchy()
display the current class name in the hierarchy at line 11.
Here’s the output from this program.
java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.text.JTextComponent javax.swing.JTextField
Note that the order of this output matches the order from the Java documentation page shown earlier.
Non Recursive Approach
Recursion is certainly an elegant solution to navigating class hierarchies, but recursive algorithms are not everyone’s cup of tea. Here’s a second version that doesn’t use recursion.
public class SuperClasses2 { public static void main(String[] args) { showHierarchy(JTextField.class); } static void showHierarchy(Class<?> c) { ArrayList<Class<?>> list = new ArrayList<Class<?>>(); while (c != null) { list.add(0, c); // add to front c = c.getSuperclass(); } for (Class<?> cls : list) System.out.println(cls.getName()); } }
You’ll note a few differences with this approach. First of all, an ArrayList
stores Class<?>
objects. Second, two loops are necessary to display the class hierarchy in the correct order. Do you see why?
After creating an empty ArrayList
of Class<?>
types at line 6, the method uses a while
loop to add class objects to the ArrayList
. Each call to c.getSuperclass()
at line 9 fetches the parent of the current class after the current class is added to the front of the ArrayList
in line 8. The while
loop terminates when the Object
class is reached for the current class.
The for
loop calls getName()
at line 12 to display the class and package names for each Class<?>
object in the ArrayList
.
The output from this program is the same as the previous one.
java.lang.Object java.awt.Component java.awt.Container javax.swing.JComponent javax.swing.text.JTextComponent javax.swing.JTextField
Note that without an ArrayList
to store Class<?>
objects, a single loop with successive calls to getSuperclass()
would make the output of class names appear in the opposite order.
Wrap Up
In this post, I showed two approaches that navigate class hierarchies with Java Reflection. The first technique was a recursive approach; the second technique was a non-recursive solution.
If you’d like to learn more about Java Reflection and other techniques like these, check out my JavaReflection LiveLesson.