Skip to content

Call Methods

We can already obtain all Field objects through Class instances, and similarly, we can obtain all Method information through Class instances. The Class class provides the following methods to obtain Method :

  • Method getMethod(name, Class...) : Get a public Method (including parent class)
  • Method getDeclaredMethod(name, Class...) : Get a Method of the current class (excluding parent class)
  • Method[] getMethods() : Get all public Method (including parent classes)
  • Method[] getDeclaredMethods() : Get all Method of the current class (excluding parent classes)

Let's take a look at the sample code:

java
// reflection
public class Main {
  public static void main(String[] args) throws Exception {
    Class stdClass = Student.class;
    // Get the public method getScore, the parameter is String:
    System.out.println(stdClass.getMethod("getScore", String.class));
    // Get the inherited public method getName, no parameters:
    System.out.println(stdClass.getMethod("getName"));
    // Get the private method getGrade, the parameter is int:
    System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
  }
}

class Student extends Person {
  public int getScore(String type) {
    return 99;
  }
  private int getGrade(int year) {
    return 1;
  }
}

class Person {
  public String getName() {
    return "Person";
  }
}

The above code first obtains Class instance of Student , and then obtains public method, inherited public method and private method respectively. The printed Method is similar:

java
public int Student.getScore(java.lang.String)
public java.lang.String Person.getName()
private int Student.getGrade(int)

A Method object contains all the information about a method:

  • getName() : Returns the method name, for example: "getScore" ;
  • getReturnType() : The return value type of the return method is also a Class instance, for example: String.class ;
  • getParameterTypes() : Returns the parameter type of the method, which is a Class array, for example: {String.class, int.class} ;
  • getModifiers() : Returns the modifiers of the method, which is an int . Different bits represent different meanings.

Call method

When we get a Method object, we can call it. Let's take the following code as an example:

java
String s = "Hello world";
String r = s.substring(6); // "world"

If you use reflection to call the substring method, you need the following code:

java
// reflection
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {
        // String object:
        String s = "Hello world";
        // Get the String substring(int) method, the parameter is int:
        Method m = String.class.getMethod("substring", int.class);
        // Call the method on the s object and get the result:
        String r = (String) m.invoke(s, 6);
        // Print call results:
        System.out.println(r); // "world"
    }
}

Notice substring() has two overloaded methods. What we get is String substring(int) method. Think about how to get String substring(int, int) method.

Calling invoke on Method instance is equivalent to calling the method. The first parameter of invoke is the object instance, that is, on which instance the method is called. The subsequent variable parameters must be consistent with the method parameters, otherwise an error will be reported.

Call static method

If the obtained Method represents a static method, when calling the static method, since there is no need to specify an instance object, the first parameter passed in by invoke method is always null . Let’s take Integer.parseInt(String) as an example:

java
// reflection
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {
        // Get the Integer.parseInt(String) method, the parameter is String:
        Method m = Integer.class.getMethod("parseInt", String.class);
        // Call the static method and get the result:
        Integer n = (Integer) m.invoke(null, "12345");
        // Print call results:
        System.out.println(n);
    }
}

Call non-public method

Similar to Field, for non-public methods, although we can obtain the method instance through Class.getDeclaredMethod() , calling it directly will get an IllegalAccessException . In order to call a non-public method, we allow it to be called through Method.setAccessible(true) :

java
// reflection
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Method m = p.getClass().getDeclaredMethod("setName", String.class);
        m.setAccessible(true);
        m.invoke(p, "Bob");
        System.out.println(p.name);
    }
}

class Person {
    String name;
    private void setName(String name) {
        this.name = name;
    }
}

Additionally, setAccessible(true) may fail. If SecurityManager exists during the JVM runtime, it will be checked according to the rules and may prevent setAccessible(true) . For example, a SecurityManager may not allow calling setAccessible(true) on package classes starting with java and javax , which can ensure the security of the JVM core library.

Polymorphism

Let's examine a situation: a Person class defines hello() method, and its subclass Student also overrides hello() method. Then, when Method obtained from Person.class is applied to the Student instance, it is called Which is the method?

java
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws Exception {
        // Get the hello method of Person:
        Method h = Person.class.getMethod("hello");
        // Call the hello method on the Student instance:
        h.invoke(new Student());
    }
}

class Person {
    public void hello() {
        System.out.println("Person:hello");
    }
}

class Student extends Person {
    public void hello() {
        System.out.println("Student:hello");
    }
}

Run the above code and find that what is printed is Student:hello . Therefore, when calling a method using reflection, the polymorphic principle is still followed: that is, the overriding method of the actual type is always called (if it exists). The above reflection code:

java
Method m = Person.class.getMethod("hello");
m.invoke(new Student());

Actually equivalent to:

java
Person p = new Student();
p.hello();

Summary

The Method object provided by Java's reflection API encapsulates all information about the method:

Method instances can be obtained through the methods of Class instances: getMethod() , getMethods() , getDeclaredMethod() , getDeclaredMethods() ;

Method information can be obtained through Method instances: getName() , getReturnType() , getParameterTypes() , getModifiers() ;

A method of an object can be called through Method instance: Object invoke(Object instance, Object... parameters) ;

Access non-public methods by setting setAccessible(true) ;

When calling methods through reflection, the principle of polymorphism is still followed.

Call Methods has loaded