Advance Java

Learn New things from Rixosys

Navigating Class Hierarchies with Java Reflection

Navigating Class Hierarchies with Java Reflection

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.