Introduction to the Java reflection API

In Java and various other languages, reflection is the technique of a program "looking in on itself". With the reflection API you can perform tasks such as enumerate all the fields of a given class, or call a method by a name supplied at runtime.

A typical way of using the reflection API involves the following steps:

There are variations on this theme depending on our exact purpose. For example, we could ask for an object representing a particular field (static or instance variable) of a given class and use this to read/write the value in question. We could also request a list of all the fields or methods on a given class which can be useful, for example, in some profiling applications.

When to use reflection?

Essentially, reflection is useful in a variety of cases when it's not convenient or possible to hard-code a given method call or field access into the code. Some typical uses include:

Example reflection code

Starting with a simple case, the following code shows how to call the String.length() method on a string using reflection (exception handling code is ommitted for clarity):

  String stringObj = "This is a string";

  Class clz = Class.forName("java.lang.String");
  Method lenMethod = clz.getDeclaredMethod("length",
      new Class[] {});
  int strlen = (Integer) lenMethod.invoke(stringObj,
      new Object[] {});

In principle, the steps are relatively straightforward. Firstly, we retrieve the Class object corresponding to the class whose method we wish to call. Then, we call getDeclaredMethod, passing in the name of the method, plus an array of parameter types, and are returned a corresponding Method object. If no such method exists, then a NoSuchMethodException is thrown. Finally, we call invoke(), passing in the object on which we wish to call the given method (which could be null in the case of a static method) and an array of objects representing the parameters (or an empty array if there are no paramters as in the String.length() method).

Note that when we call invoke() on the given Method object, we are passed the method's return value as an Object. In this case, we know that the specific return type is a primitive int, and we will be returned a corresponding Integer wrapper object by the invoke() method (because this method must always return an Object). So we safely cast the return value to an Integer. In addition, Java 5 onwards allows us to directly assign this Integer object to a primitive int variable (a process called "auto-unboxing")— the compiler will automatically insert a call to intValue() for us.

Next: further observations/variations on reflective method calls

Following on from the above basic template for making a reflexive call, on the next page we look at further details of calling a method via reflection.

If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.