Appearance
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 apublic
Method
(including parent class)Method getDeclaredMethod(name, Class...)
: Get aMethod
of the current class (excluding parent class)Method[] getMethods()
: Get allpublic
Method (including parent classes)Method[] getDeclaredMethods()
: Get allMethod
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 anint
. 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.