Java Reflection for Methods

1. Overview

The java.lang.reflect.Method class provides APIs to access information about a method's modifiers, return type, parameters, annotations, and thrown exceptions. It also is used to invoke methods.

The below class diagram shows java.lang.reflect.Method class provides APIs to access information about a method's modifiers, return type, parameters, annotations, and thrown exceptions.
Java Reflection for Methods

2. Reflection Method API Examples

  • Obtaining Method Type Information
  • Obtaining Names of Method Parameters
  • Retrieving and Parsing Method Modifiers
  • Get Public Method
  • Invoking Public Method
  • Get All Public Methods
In this guide, we will look into all the above important methods of Class.

2.1 Obtaining Method Type Information

This example illustrates how to enumerate all of the declared methods in a given class and retrieve the return, parameter, and exception types for all the methods of the given name.
public static void reflectionMethodExamples() {
 final String fmt = "%24s: %s%n";
 try {
     Class<?> c = Class.forName("com.javaguides.reflection.methods.Employee");
     Method[] allMethods = c.getDeclaredMethods();
     for (Method m : allMethods) {
         out.format("%s%n", m.toGenericString());

         out.format(fmt, "ReturnType", m.getReturnType());
         out.format(fmt, "GenericReturnType", m.getGenericReturnType());

         Class<?>[] pType = m.getParameterTypes();
         Type[] gpType = m.getGenericParameterTypes();
         for (int i = 0; i < pType.length; i++) {
             out.format(fmt, "ParameterType", pType[i]);
             out.format(fmt, "GenericParameterType", gpType[i]);
         }

         Class<?>[] xType = m.getExceptionTypes();
         Type[] gxType = m.getGenericExceptionTypes();
         for (int i = 0; i < xType.length; i++) {
             out.format(fmt, "ExceptionType", xType[i]);
             out.format(fmt, "GenericExceptionType", gxType[i]);
         }
     }
     // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
}
Output:
public java.lang.String com.javaguides.reflection.methods.Employee.getName()
              ReturnType: class java.lang.String
       GenericReturnType: class java.lang.String
public int com.javaguides.reflection.methods.Employee.getId()
              ReturnType: int
       GenericReturnType: int
public void com.javaguides.reflection.methods.Employee.setName(java.lang.String)
              ReturnType: void
       GenericReturnType: void
           ParameterType: class java.lang.String
    GenericParameterType: class java.lang.String
private int com.javaguides.reflection.methods.Employee.getAge()
              ReturnType: int
       GenericReturnType: int
public void com.javaguides.reflection.methods.Employee.setId(int)
              ReturnType: void
       GenericReturnType: void
           ParameterType: int
    GenericParameterType: int

2.2 Obtaining Names of Method Parameters

The MethodParameterSpy example illustrates how to retrieve the names of the formal parameters of all constructors and methods of a given class. The example also prints other information about each parameter.
package com.javaguides.reflection.methods;

import static java.lang.System.out;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
 
public class MethodParameterSpy {
     
    private static final String  fmt = "%24s: %s%n";
 
    // for the morbidly curious
    <E extends RuntimeException> void genericThrow() throws E {}
     
    public static void printClassConstructors(Class c) {
        Constructor[] allConstructors = c.getConstructors();
        out.format(fmt, "Number of constructors", allConstructors.length);
        for (Constructor currentConstructor : allConstructors) {
            printConstructor(currentConstructor);
        }  
        Constructor[] allDeclConst = c.getDeclaredConstructors();
        out.format(fmt, "Number of declared constructors",
            allDeclConst.length);
        for (Constructor currentDeclConst : allDeclConst) {
            printConstructor(currentDeclConst);
        }          
    }
     
    public static void printClassMethods(Class c) {
       Method[] allMethods = c.getDeclaredMethods();
        out.format(fmt, "Number of methods", allMethods.length);
        for (Method m : allMethods) {
            printMethod(m);
        }        
    }
     
    public static void printConstructor(Constructor c) {
        out.format("%s%n", c.toGenericString());
        Parameter[] params = c.getParameters();
        out.format(fmt, "Number of parameters", params.length);
        for (int i = 0; i < params.length; i++) {
            printParameter(params[i]);
        }
    }
     
    public static void printMethod(Method m) {
        out.format("%s%n", m.toGenericString());
        out.format(fmt, "Return type", m.getReturnType());
        out.format(fmt, "Generic return type", m.getGenericReturnType());
                 
        Parameter[] params = m.getParameters();
        for (int i = 0; i < params.length; i++) {
            printParameter(params[i]);
        }
    }
     
    public static void printParameter(Parameter p) {
        out.format(fmt, "Parameter class", p.getType());
        out.format(fmt, "Parameter name", p.getName());
        out.format(fmt, "Modifiers", p.getModifiers());
        out.format(fmt, "Is implicit?", p.isImplicit());
        out.format(fmt, "Is name present?", p.isNamePresent());
        out.format(fmt, "Is synthetic?", p.isSynthetic());
    }
     
    public static void main(String... args) {        
 
        try {
            printClassConstructors(Class.forName("com.javaguides.reflection.methods.Employee"));
            printClassMethods(Class.forName("com.javaguides.reflection.methods.Employee"));
        } catch (ClassNotFoundException x) {
            x.printStackTrace();
        }
    }
}
Output:
  Number of constructors: 1
public com.javaguides.reflection.methods.Employee()
    Number of parameters: 0
Number of declared constructors: 1
public com.javaguides.reflection.methods.Employee()
    Number of parameters: 0
       Number of methods: 5
public java.lang.String com.javaguides.reflection.methods.Employee.getName()
             Return type: class java.lang.String
     Generic return type: class java.lang.String
public int com.javaguides.reflection.methods.Employee.getId()
             Return type: int
     Generic return type: int
public void com.javaguides.reflection.methods.Employee.setName(java.lang.String)
             Return type: void
     Generic return type: void
         Parameter class: class java.lang.String
          Parameter name: arg0
               Modifiers: 0
            Is implicit?: false
        Is name present?: false
           Is synthetic?: false
public void com.javaguides.reflection.methods.Employee.setId(int)
             Return type: void
     Generic return type: void
         Parameter class: int
          Parameter name: arg0
               Modifiers: 0
            Is implicit?: false
        Is name present?: false
           Is synthetic?: false
private int com.javaguides.reflection.methods.Employee.getAge()
             Return type: int
     Generic return type: int

2.3 Retrieving and Parsing Method Modifiers

There several modifiers that may be part of a method declaration:
  • Access modifiers: public, protected, and private
  • Modifier restricting to one instance: static
  • Modifier prohibiting value modification: final
  • Modifier requiring override: abstract
  • Modifier preventing reentrancy: synchronized
  • Modifier indicating implementation in another programming language: native
  • Modifier forcing strict floating point behavior: strictfp
  • Annotations
The MethodModifierSpy example lists the modifiers of a method with a given name. It also displays whether the method is synthetic (compiler-generated), of variable arity, or a bridge method (compiler-generated to support generic interfaces).
package com.javaguides.reflection.methods;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import static java.lang.System.out;

public class MethodModifierSpy {

    private static int count;

    private static synchronized void inc() {
       count++;
    }

    private static synchronized int cnt() {
        return count;
    }

    public static void main(String... args) {
     try {
         Class<?> c = Class.forName("java.lang.Object");
         Method[] allMethods = c.getDeclaredMethods();
         for (Method m : allMethods) {
           if (!m.getName().equals("wait")) {
              continue;
           }
           out.format("%s%n", m.toGenericString());
           out.format("  Modifiers:  %s%n", Modifier.toString(m.getModifiers()));
           out.format("  [ synthetic=%-5b var_args=%-5b bridge=%-5b ]%n", m.isSynthetic(), m.isVarArgs(),
           m.isBridge());
           inc();
         }
         out.format("%d matching overload%s found%n", cnt(), (cnt() == 1 ? "" : "s"));

         // production code should handle this exception more gracefully
       } catch (ClassNotFoundException x) {
            x.printStackTrace();
       }
    }
}
Output:
public final void java.lang.Object.wait() throws java.lang.InterruptedException
  Modifiers:  public final
  [ synthetic=false var_args=false bridge=false ]
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
  Modifiers:  public final
  [ synthetic=false var_args=false bridge=false ]
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
  Modifiers:  public final native
  [ synthetic=false var_args=false bridge=false ]
3 matching overloads found
Let's First create Employee.java class and then we will apply all the reflection API's on Employee class methods.

Employee.java

package com.javaguides.reflection.methods;

public class Employee {
 
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2.4 Get Public Method

We can use getMethod() to get a public method of a class, we need to pass the method name and parameter types of the method. If the method is not found in the class, reflection API looks for the method in a superclass.
Class<?> concreteClass = Class.forName("com.javaguides.reflection.methods.Employee");
Method method = concreteClass.getMethod("getName");
System.out.println(method.getName());

Method method2 = concreteClass.getMethod("getId", String.class);
System.out.println(method2.getName());

Method putMethod = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
// get method parameter types, prints "[class java.lang.Object, class
// java.lang.Object]"
System.out.println(Arrays.toString(putMethod.getParameterTypes()));
// get method return type, return "class java.lang.Object", class
// reference for void
System.out.println(putMethod.getReturnType());
// get method modifiers
System.out.println(Modifier.toString(method.getModifiers()));
Output:
getName
setId
[class java.lang.Object, class java.lang.Object]
class java.lang.Object
public

2.5 Invoking Public Method

We can use invoke() method of Method object to invoke a method, in below example code let's invoke put method on HashMap using reflection.
Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
Map<String, String> hm = new HashMap<>();
method.invoke(hm, "key", "value");
System.out.println(hm); // prints {key=value}

2.6 Get All Public Methods

getMethods() method returns the array of public methods of the Class including public methods of it’s superclasses and super interfaces.
Class<?> concreteClass = Class.forName("com.javaguides.reflection.methods.Employee");
Method[] methods = concreteClass.getMethods();
for (Method method : methods) {
    System.out.println(method.getName());
}
Output:
getName
getId
setName
setId
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

3. Reference

Comments