调用方法
789字约3分钟
2024-08-10
我们可以通过 Class
实例获取所有 Method
信息
Class类提供了以下几个方法来获取Method
Method getMethod(name, Class...)
:获取某个public
的Method
(包括父类)Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method
(不包括父类)Method[] getMethods()
:获取所有public
的Method
(包括父类)Method[] getDeclaredMethods()
:获取当前类的所有Method
(不包括父类)
public class Main {
public static void main(String[] args) throws Exception {
Class stdClass = Student.class;
// 获取 public 方法 getScore,参数为 String
System.out.println(stdClass.getMethod("getScore", String.class));
// 获取继承的 public 方法 getName,无参数
System.out.println(stdClass.getMethod("getName"));
// 获取 private 方法 getGrade ,参数为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";
}
}
上述代码首先获取 Student
的 Class
实例,然后,分别获取 public
方法、继承的 public
方法以及 private
方法,打印出的 Method
public int com.marui.reflection.Student.getScore(java.lang.String)
public java.lang.String com.marui.reflection.Person.getName()
private int com.marui.reflection.Student.getGrade(int)
一个 Method
对象包含一个方法的所有信息
getName()
:返回方法名称,例如:getScore
getReturnType()
:返回方法返回值类型,也是一个Class
实例,例如:String.class
getParameterTypes()
:返回方法的参数类型,是一个Class数组,例如:{String.class, int.class}
getModifiers()
:返回方法的修饰符,它是一个int
,不同的bit
表示不同的含义
调用方法
当我们获取到一个 Method
对象时,就可以对它进行调用,正常调用
String str = "Hello world";
String r = str.substring(6); // "world"
用反射来调用substring
方法
public static void main(String[] args) throws Exception {
// String 对象
String str = "Hello World";
// 获取 String substring(int) 方法,参数为 int
Method m = String.class.getMethod("substring", int.class);
// 在 str 对象上调用该方法并获取结果
String res = (String) m.invoke(str, 6);
// 打印调用结果,World
System.out.println(res);
}
对 Method
实例调用 invoke
就相当于调用该方法,invoke
的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错
调用静态方法
调用静态方法时,由于无需指定实例对象,所以 invoke
方法传入的第一个参数永远为 null
public static void main(String[] args) throws Exception {
// 获取 Integer.parseInt(String) 方法,参数为 String
Method m = Integer.class.getMethod("parseInt", String.class);
// 调用该静态方法并获取结果
Integer n = (Integer) m.invoke(null, "123");
// 打印调用结果:123
System.out.println(n);
}
调用非public方法
我们通过 Method.setAccessible(true)
允许其调用,直接调用将得到一个 IllegalAccessException
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person();
Method m = person.getClass().getDeclaredMethod("getName", String.class);
m.setAccessible(Boolean.TRUE);
String name = (String) m.invoke(person, "张三");
System.out.println(name); // 张三
}
}
class Person {
public String getName(String name) {
return name;
}
}
多态
使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)
public class Main {
public static void main(String[] args) throws Exception {
Method m = Person.class.getMethod("hello");
String res = (String) m.invoke(new Student());
System.out.println(res); // Student:Hello
}
}
class Student extends Person {
@Override
public String hello() {
return "Student:Hello";
}
}
class Person {
public String hello() {
return "Person:Hello";
}
}
Method m = Person.class.getMethod("hello");
m.invoke(new Student());
// 上面两行反射代码相当于下面两行代码
Person p = new Student();
p.hello();