浅谈利用反射(四)(框架设计的灵魂)技术获取类中的成员方法,并运行获取到的方法(重点)

实现步骤:

  1. 获取Person类的class文件对象
  2. 使用class文件对象中的方法getMethod / getMethds获取类中的成员方法Method
  3. 使用Method类中的方法invoke执行获取到的方法

现在拆分开详细描述:

第一步:获取类的class文件对象

详见:https://blog.csdn.net/qq_45083975/article/details/91959244

第二步:使用class文件对象中的方法getMethod / getMethds获取类中的成员方法Method

  1. Method[] getMethods() 获取类中所有的公共成员方法,包含继承的和实现的(一般不采用)
  2. Method[] getDeclaredMethods() 包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
  3. Method getMethod(String name, Class<?>… parameterTypes) 获取指定公共成员方法。
  4. Method getDeclaredMethod(String name, Class<?>… parameterTypes) 获取指定已声明(公共、保护、默认(包)访问和私有)方法。
参数说明:

      String name:获取的方法名字
      比如:getName,setName,method 等
      Class<?>… parameterTypes:成员方法参数列表的class文件对象
      比如:int.class,double.class,String.class,Student.class 等

注意:

      类中没有指定的方法,会抛出NoSuchMethodException 没有方法异常

注意:

   在Method类中有一个方法
         String getName() 以 String 形式返回此 Method 对象表示的方法名称。

第三步:使用Method类中的方法invoke执行获取到的方法

Object invoke(Object obj, Object… args)
      对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
注意:
      指定参数的指定对象这就用到了前面所说的快速创建对象的方法。使用newInstance()

参数说明:

      Object obj:使用反射技术执行方法,需要对象的支持;执行哪个类中的方法,就传递哪个类的对象。这个对象可以使用反射快速创建对象的方式获取
      Object… args:调用方法传递的实际参数
返回值:
      方法的返回值
            方法有返回值,获取的就是方法的返回值
            方法没有返回值,返回值类型是void,值就是null(没有必要接收)
那么假如需要获取私有的构造方法:private void method()
      私有方法没有权限运行,会抛出IllegalAccessException:非法访问异常
      可以使用Method的父类AccessibleObject中的方法,取消权限检查
            void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。
                  值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
                  值为 false 则指示反射的对象应该实施 Java 语言访问检查。
(上面的这种获取私有的构造方法的方式属于暴力反射,不推荐使用,因为它破坏了类的封装性

下面我们举例说明:

package com.ccc.demo02Reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo04ReflectMethod {
    public static void main(String[] args) throws Exception {
        
        //1.获取Person类的class文件对象
        Class clazz = Class.forName("com.ccc.demo03domain.Person");
        
        //2.使用class文件对象中的方法getMethod/getMethds获取类中的成员方法Method
        /*
            Method[] getMethods()  获取类中所有的公共成员方法,包含继承的和实现的
            Method[] getDeclaredMethods() 包括公共、保护、默认(包)访问和私有方法,
            								但不包括继承的方法。
         */
        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        
        System.out.println("======================");
        
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method);
        }
        
        System.out.println("======================");
        
        /*
            Method getMethod(String name, Class<?>... parameterTypes)  获取指定公共成员方法。
            Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
            								获取指定已声明(公共、保护、默认(包)访问和私有)方法。
            参数:
                String name:获取的方法名字 
                										比如:getName,setName,method
                Class<?>... parameterTypes:成员方法参数列表的class文件对象
                			比如:int.class,double.class,String.class,Student.class 等
             注意:
                类中没有指定的方法,会抛出NoSuchMethodException 没有方法异常
         */
        //获取 public String getName()
        Method getNameMethod = clazz.getMethod("getName");
        System.out.println(getNameMethod);
        //输出:public java.lang.String com.ccc.demo03domain.Person.getName()

        //获取 public void setName(String name)
        Method setNameMethod = clazz.getMethod("setName", String.class);
        System.out.println(setNameMethod);
        //输出:public void com.ccc.demo03domain.Person.setName(java.lang.String)

        //获取 private void method()
        Method privateMethod = clazz.getDeclaredMethod("method");
        System.out.println(privateMethod);
        //输出:private void com.ccc.demo03domain.Person.method()

        /*
            注意:
                在Method类中有一个方法
                    String getName()  以 String 形式返回此 Method 对象表示的方法名称。
         */
        String name = setNameMethod.getName();
        System.out.println(name);	//输出:setName
        System.out.println("---------------------------------------");

        //3.使用Method类中的方法invoke执行获取到的方法
        /*
            Object invoke(Object obj, Object... args)
                对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
            参数:
                Object obj:使用反射技术执行方法,需要对象的支持;执行哪个类中的方法,就传递哪个类的对象
                        这个对象可以使用反射快速创建对象的方式获取
                Object... args:调用方法传递的实际参数
            返回值:
                方法的返回值
                    方法有返回值,获取的就是方法的返回值
                    方法没有返回值,返回值类型是void,值就是null(没有必要接收)
         */
        Object obj = clazz.newInstance();

        //public String getName()
        Object v1 = getNameMethod.invoke(obj);		//就相当于调用类中getName方法
        System.out.println("v1:"+v1);				//输出:v1:null 成员变量的默认值

        //public void setName(String name)
        Object v2 = setNameMethod.invoke(obj, "赵四");	//就相当于调用类中setName("赵四")方法
        System.out.println("v2:"+v2);					//输出:v2:null  方法没有返回值

        v1 = getNameMethod.invoke(obj);					//就相当于调用类中getName方法
        System.out.println("v1:"+v1);					//输出:v1:赵四

        /*
            private void method()
            私有方法没有权限运行,会抛出IllegalAccessException:非法访问异常
            可以使用Method的父类AccessibleObject中的方法,取消权限检查
                 void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。
                    值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
                    值为 false 则指示反射的对象应该实施 Java 语言访问检查。
         */
        privateMethod.setAccessible(true);				//取消权限检查-->暴力反射
        privateMethod.invoke(obj);
    }
}

Person类:

package com.ccc.demo03domain;

public class Person {
    private String name;
    private int age;
    private String sex;

    public Person() {
        System.out.println("Person类的空参数构造方法");
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("Person类的全参数构造方法");
    }

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person类的私有构造方法");
    }

    //私有方法
    private void method(){
        System.out.println("Person类的私有方法");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45083975/article/details/91967838