通过反射调用方法
获得pubblic和非public的方法
上一节中,我们使用getField()等获得了类的字段。同理,我们这里使用getMethod()。
- getMethod()只能获得public方法
- getDeclaredMethod()可以获取所有方法,不管访问修饰符
- getMethods()获取所有public方法
- getDeclaredMethods()获取所有方法
举例:
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
// 拿到大Class对象
Class<? extends Person> pClass = p.getClass();
// 获得方法
Method eat = pClass.getDeclaredMethod("eat");
eat.setAccessible(true);
Method sleep = pClass.getMethod("sleep");
eat.invoke(p);
sleep.invoke(p);
}
}
class Person {
private void eat(){
System.out.println("i can eat");
}
public void sleep(){
System.out.println("i can sleep");
}
}
分析
输出:
i can eat
i can sleep
该例子中,我们通过getDeclaredMethod()来获得私有方法,通过getMethod()来获得public方法。
调用上述方法后获得了Method对象。
然后再调用Method对象里的具体方法invoke()
可以看到我使用了setAccessible(true);,这个和获取字段同理,当你只是获得对象是可以使用getDelaredMethod(),但是你要使用invoke()调用它的方法,当且仅当修饰符为private你必须使用setAccessible(true);让其忽略修饰符。
上面我们演示了获取public和private方法,下面我们对其它类型的方法进行演示。
获得静态方法
当获得的是静态方法是,我们的invoke()方法第一个参数(执行对象)就应该为null, 静态方法是一加载就存在的,不需要实例即可运行。
执行下面的方法
sleep.invoke(null);
获得父类方法
获得父类方法与获得子类方法没有区别,直接通过方法名字。
有一种特殊情况,当子类与父类拥有同名方法,最终获得的是什么方法呢?
答案是子类的方法,因为优先获得的是本类的方法。
方法重载
如下,当我有多个重载方法,该怎么获得?
class Person {
void sleep(String name){
System.out.println("i can sleep");
}
void sleep(String name, String time){
System.out.println("i can sleep");
}
}
答案:通过getmethod()的参数,它的第二个参数为该方法需要传入的参数类型。
public class Main {
public static void main(String[] args) throws Exception {
Class<Person> personClass = Person.class;
// 获得方法
Method sleep1 = personClass.getDeclaredMethod("sleep", String.class);
Method sleep2 = personClass.getDeclaredMethod("sleep", String.class, String.class);
sleep1.invoke(new Person(), "小红");
sleep2.invoke(new Person(), "小胖", "一小时");
}
}
Method对象
典型的Method对象方法:
- invoke():调用这个方法。
- getName():获取方法名。
- getParameterTypes():获取参数类型数组。
- getReturnType():获取返回值类型。
- getDeclaringClass():获取声明这个方法的类。
- getAnnotation(), 获得方法上的注解,要指定你要获得的注解类。
- isAnnotationPresent(), 判断是否有注解