4 min read

Method Reflection in Java

Method reflection allows you to obtain information about the method signature as well as invoke the method.
Method Reflection in Java

Method Reflection

Method reflection is a runtime feature that allows you to dynamically invoke methods in a class at runtime. You can also find what modifiers, return type, parameters, and checked exceptions are on the method signature. Method reflection is done using the java.reflect.Method class. Instances of this class can be obtained from java.lang.Class. The following class will be used for the examples in this article.

package press.bytesize;

public class Person {

    public int id() {
        return 10;
    }

    public void sayHello() throws IOException {
        System.out.println("Hello");
    }
    
    private void sayHello(final String name) throws IOException {
        System.out.println("Hello " + name);
    }
}

Obtaining java.reflect.Method Instances

Once a java.lang.Class instance is obtained for the class you are wanting to use reflection on, you can obtain a java.reflect.Method instance a few different ways depending on your use case. Unlike java.lang.Class, java.reflect.Method instances are not singletons.

A java.reflect.Method instance for each of the methods above on the User class can be obtained using the getDeclaredMethod() method. If a method doesn't exist, the getDeclaredMethod() will throw a NoSuchMethodException.

final Method id = User.class.getDeclaredMethod("id");
final Method sayHello = User.class.getDeclaredMethod("sayHello");
final Method sayHelloOverload = 
        User.class.getDeclaredMethod("sayHello", String.class);

If a method is overloaded, you must specify the method parameters types for that method.

All methods in the User class can be obtained using the getDeclaredMethods() method.

final Method[] methods = User.class.getDeclaredMethods();

If you are working with public methods, you can use getMethod() and getMethods() instead. These will only return a method if it is public and will throw a NoSuchMethodException if the method doesn't exist or if it isn't public.

java.reflect.Method Class

Methods have modifiers, a return type, a name, parameters, and exceptions. You can print out the method signature using the toGenericString() method.

final Method sayHello = 
        User.class.getDeclaredMethod("sayHello", String.class);

System.out.println(sayHello.toGenericString());

This will print the following:

public void press.bytesize.User.sayHello(java.lang.String) throws IOException

Method Accessibility

To invoke a method using reflection, methods must either be marked as public or be accessible before you can invoke them. This is done using the setAccessible() method. If a method cannot be accessed due to the lack of permission defined by the SecurityManager, a SecurityException will be thrown. These permissions are different from the access modifier.

final Method id = User.class.getDeclaredMethod("id");
id.setAccessible(true);

Java 9 introduced the trySetAccessible() method. This will return true if you have permission to make it accessible; otherwise, it will return false.

final Method idMethod = User.class.getDeclaredMethod("id");

if (idMethod.trySetAccessible()) {
    // Do something...
} else {
    // You do not have permissions...
}

Invoking Methods

Invoking methods is done using the invoke() method. This method requires you to pass an instance of the object that you are wanting to invoke the method on and the parameters for that method. This takes an object as the first parameter and a varargs parameter for the second parameter. For methods not marked as public, you must make the java.reflect.Method instance accessible before invoking the method.

final var user = new User();
final Method sayHelloOverload = 
        user.getClass().getDeclaredMethod("sayHello", String.class);

sayHelloOverload.setAccessible(true);
sayHelloOverload.invoke(user, "Mike Smith");

This invokes the sayHello() method that takes a String as a parameter. Since it is a varargs method.

Method Return Type

The method return type can be obtained with the getReturnType() method.

final Method id = User.class.getDeclaredMethod("id");
final Class<?> returnType = id.getReturnType();

This returns a java.lang.Class instance of the return type.

Method Name

You can get the method's name using the getName() method.

final Method id = User.class.getDeclaredMethod("id");
System.out.println(id.getName());

Method Parameters

Parameters can have a final modifier, a type, and a name. Each of these is represented in the java.lang.Parameter class. You can get an array of each of the parameters in a method using the getParameters() method.

final Method id = User.class.getDeclaredMethod("id");
final Parameter[] parameters = id.getParameters();

You can also get a count of the number of parameters a method has using the getParameterCount() method.

final Method id = User.class.getDeclaredMethod("id");
final int parameterCount = id.getParameterCount();

Method Exceptions

You can get an array of the exceptions defined in the throws clause of the method signature using getExceptionTypes(). This returns an array of java.lang.Classes. If there isn't any exception defined on the throws clause, this returns an empty array.

final Method id = User.class.getDeclaredMethod("id");
final Class<?>[] exceptionTypes = id.getExceptionTypes();

Method Modifiers

You can find out if a method is marked with a specific modifier using the getModifiers() method. This returns an int. You can then use the java.lang.Modifier class to see if a method has a specific modifier.

final Method id = User.class.getDeclaredMethod("id");

System.out.println(Modifier.isPublic(id.getModifiers())); // true
System.out.println(Modifier.isFinal(id.getModifiers())); // false

Java 20 introduced the accessFlags() method. This returns a java.util.Set of java.lang.reflect.AccessFlags. You can then check to see if the Set contains an AccessFlag.

final Method id = User.class.getDeclaredMethod("id");
final Set<AccessFlag> flags = id.accessFlags();

System.out.println(flags.contains(AccessFlag.PUBLIC)); // true
System.out.println(flags.contains(AccessFlag.FINAL)); // false

Superclass Methods

When working with method reflection, you will only be able to access the methods in the Java source file you are working in. Methods are not inherited with reflection. It is only what is defined in the Java source file that you can access for that class. If you have a method in a superclass you are wanting to access, you have to specify the superclass instead to get to the method. If the User class had a superclass, you could access it using the getSuperclass() method.

public class SuperclassUser {
    public void greet() {
    }
}

public class User extends SuperclassUser {
}

final Method superGreet = SuperclassUser.class.getDeclaredMethod("greet");

// or
final Method subGreet = User.class.getSuperClass().getDeclaredMethod("greet");

Conclusion

Method reflection allows you to get information such as the modifiers, return type, method name, parameters, and exceptions. You can invoke a method using reflection. When doing so, you need an instance of that class that you invoke the method on.