调用方法
约 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():返回方法名称,例如:getScoregetReturnType():返回方法返回值类型,也是一个Class实例,例如:String.classgetParameterTypes():返回方法的参数类型,是一个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();