通过反射获取类中的方法并调用

202 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

这篇文章我们来介绍一下如何通过反射来获取Class 中的方法,并学习如何调用这些方法。我们使用这篇文章中的类结构作为例子来介绍。

获取并调用类中的public 方法

首先我们来看一下如何获取并调用类中的public 方法。在示例类中的public 方法是doHomework、playGame。我们这里使用doHomework 来做介绍。

Class<?> clazz = Student.class;
try {
    Method doHomework = clazz.getMethod("doHomework", String.class);
    Student student = new Student("Jack", 23);
    doHomework.invoke(student, "math");
}
catch (Exception e) {
    e.printStackTrace();
}

我们来拆解一下上面这段代码。首先,我们需要通过clazz.getMethod 方法,获得这个“方法对象”。

在getMethod 方法中,第一个参数是要获取的方法名,之后的参数为待获取的方法的所有的参数类型。待获取的方法中有多少个参数,那么在第一个参数后面就会有多少个参数。

在我们得到了method 对象之后,我们就可以调用method 对象的invoke 方法去调用这个方法了。

在invoke 方法中,第一个参数是实例化的对象,第一个参数之后的参数和待调用的函数一致,输入的是待处理的参数。

获取并调用类中的private 方法

在示例类中,私有方法是cleanClassroom,我们来看一下如何获取并调用私有方法。

try {
    Method cleanClassroom = clazz.getDeclaredMethod("cleanClassroom");
    work.setAccessible(true);
    Student student = new Student("Amy", 29);
    work.invoke(studnet);
}
catch (Exception e) {
    e.printStackTrace();
}

细心的读者可以很快地发现,在获取私有方法的时候,和获取私有属性的步骤十分类似。获取私有方法,需要调用getDeclaredMethod 方法,同时需要调用setAccessible(true) 来允许私有方法可以访问。

获取并调用类中的静态方法

在示例类中的静态方法为getMaxAge,对于这个方法,我们来看一下如何通过反射来操作它。

try {
    Method getMaxAget = clazz.getDeclaredMethod("getMaxAget");
    getMaxAget.setAccessible(true);
    // 由于这个是静态方法,所以在调用它的时候,就不需要传入实例化对象,所以只传入一个null 即可。
    Object value = getMaxAget.invoke(null);
    System.out.println("the value from getMaxAge is: " + value);
} catch (Exception e) {
    e.printStackTrace();
}

细心的读者也可以发现,在调用静态方法的时候,很像处理静态字段一下,在invoke 中的第一个参数只需要传入null 就行了。

获取并调用类中的所有方法

我们最后来看一下如何获取并调用类中的所有的方法。

Student student = new Student();
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
    Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
    try {
        declaredMethod.setAccessible(true);
        Object result;
        if (parameterTypes.length == 0) {
            result = declaredMethod.invoke(student);
        } else {
            result = declaredMethod.invoke(student, "hi!");
        }
        System.out.println("method name: " + declaredMethod.getName() + ", paramenter type: " + Arrays.toString(parameterTypes) + ", return value: " + result);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

对比与获取类中的所有字段,我们发现获取所有方法也很类似,方法签名也比较像。

我们只需要使用clazz.getDeclaredMethods(); 就可以获得到类中的所有方法了。

总结

这篇文章我们介绍的就是如何通过反射来获取类中的方法了。看似内容比较多,其实也是很有结构的。对于读者来说也是比较好阅读理解。希望读者可以加以运用,一定会带来很多方法之处。