Java反射机制,通过对象访问调用类的私有成员属性或者方法

Java反射机制原理
Java中万物皆对象,类class也是对象,是一个名为Class的类的对象。
所以就可以通过这个Class类类型的对象class,用对象访问类的属性和方法。

Class是对类的抽象(每个类对应一份字节码)。一般情况下,比如A a = new A();
直接通过a对象调用方法即可。但是在有些场景下,这样是做不到的,
比如类名A是通过参数传递过来的,这时候你就无法通过new的方法创建对象,需要先加载这个类,
获取Method对象,然后用Method已反射的形式调用相应的方法。

如何获得Class的类类型

先声明一个类text的对象t;

text1 t = new text1();

有三种方式可以来获得类类型:

Class t0 = text.class;//通过类获得类类型,说明Class类中隐含着一个class的对象
Class t1 = t.getClass();//通过对象获得类类型
Class t2 = null;
text t4 = null;
try {
    t2 = Class.forName("classReflex.text");// 通过类的全名获得类类型
    t4 = (text) t0.newInstance();// 通过类类型获得类的对象
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    e.printStackTrace();
}

进入正题:通过类类型来实现对类的成员变量、方法、构造方法的访问和调用。

首先是一个类text1

public class text1 {

    public int x;
    protected boolean b;
    private String s;

    public text1() {
        // TODO Auto-generated constructor stub
    }

    public void f0() {
        System.out.println("我爱计算机!我爱Android!");
    }

    private void f0_private() {
        System.out.println("就算我是私有的方法!我爱计算机!我爱Android!");
    }

    public void f1(int i, String s1, boolean b) {

    }

    public int f2(int i, int s1, int b) {
        return i;
    }

    public String f3(String i, String s1, String b) {
        return i;
    }

}

利用对象获得类的成员变量

  1. 利用对象获得类类型Class c = object.getClass();
  2. 通过getName()方法获得类的名称。
  3. getDeclaredFields()会返回类自己定义的所有的成员属性的Field集合,(领域)
  4. 通过Class type = field.getType();获得属性的类类型,getName()就能得到属性的具体类型了
  5. 关于属性的调用类似于下文的方法的调用
public static void printClassAttribute(Object object) {
        // 首先获得类的信息,先获得类的类型。
        Class c = object.getClass();
        // 获得类的名字,传入的是什么类型,就表示什么类型,而不是父类object类型。
        System.out.println("类的名称:" + c.getName());
        System.out.println("类的成员属性:");
        Field[] Fields = c.getDeclaredFields();
        if (Fields.length > 0) {
            for (Field field : Fields) {
                Class type = field.getType();
                System.out.println("field.getName()-->" + field.getName());
                System.out
                        .println(field.getModifiers() + " " + type.getSimpleName() + 
                        " m" + type.getSimpleName() + ";");
            }
        } else {
            System.out.println("没有成员属性");
        }
    }

利用对象获得类的成员方法

通过类类型对象访问类所有的方法

  1. c.getDeclaredMethods();通过类类型的对象获得方法类的对象集合Method的集合。
  2. 通过Method对象的getReturnType()获得方法的返回类型的类类型对象
  3. 同股票method.getParameterTypes()获得方法的输入形参的类类型集合。之后就好办啦,通过类类型得到类型。

通过类类型对象调用类的方法

  1. Methodm m= c.getMethod(“方法名”, 形参的类类型集合);获得指定方法的对象
  2. 如果该方法是私有方法需要现声明该方法访问无障碍setAccessible(true);
  3. 之后调用m.invoke(c.newInstance,”实参”集合);调用类的方法。
  4. 当然如果是静态方法就不需要传入类型对象,只需要传入类类型对象c就可以了
public static void printClassMethod(Object object) {
        // 首先获得类的信息,先获得类的类型。
        Class c = object.getClass();
        // 获得类的名字,传入的是什么类型,就表示什么类型,而不是父类object类型。
        System.out.println("类的名称:" + c.getName());
        System.out.println("类的成员方法:");
        /*
         * Method类型是方法的类型。即:方法也是对象,是类型Method的对象
         * getMethods()获得类的所有成员方法,包括从父类继承来的方法
         * getDeclaredMethods()获得类自己定义的成员方法。不包含父类的方法
         */
        // Method[] methods = c.getMethods();
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            // 获得方法的返回值的类类型
            Class returnTyoe = method.getReturnType();
            System.out.print(returnTyoe.getSimpleName() + " " + method.getName() + "(");
            // 获得方法所有的形参数组
            Class[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                Class parameterType = parameterTypes[i];
                if (i != 0)
                    System.out.print(" , ");
                System.out.print(parameterType.getSimpleName() + " par" + i);
            }
            System.out.println(");");
        }
        System.out.println("methods.length-->" + methods.length);
        /**
         * 利用反射调用public方法f0();
* 先获得方法的对象Method类型的,由方法对象调用对象的方法 */
Method m; try { m = c.getMethod("f0", null); m.invoke(c.newInstance(), null);// 通过类的对象调用对象的方法,后面的是参数 // 如果的调用静态方法,就不必传入类的对象了,而只需要传递类类型就可以了m.invoke(c, null); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } /** * 利用反射调用private方法f0();
* m_private.setAccessible(true);//访问私有方法的关键步骤,设置为访问无障碍 */
Method m_private; try { m_private = c.getDeclaredMethod("f0_private", null); m_private.setAccessible(true);// 访问私有方法的关键步骤,设置为访问无障碍,但是也只能访问该类类型能访问到的方法,子类就无法访问父类的私用方法 m_private.invoke(c.newInstance(), null); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException| InvocationTargetException | InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

利用对象获得类的构造方法

和调用成员方法类似,不再做过多讲解。

public static void printStructureMethod(Object object) {
        Class c = object.getClass();
        // 获得类的名字,传入的是什么类型,就表示什么类型,而不是父类object类型。
        System.out.println("类的名称:" + c.getName());
        System.out.println("类的构造方法:");
        Constructor[] constructors = c.getConstructors();
        for (int i = 0; i < constructors.length; i++) {
            Constructor constructor = constructors[i];
            System.out.print(constructor.getName() + " (");
            Class[] parameterTypes = constructor.getParameterTypes();
            for (int j = 0; j < parameterTypes.length; j++) {
                Class parameterType = parameterTypes[j];
                if (j != 0)
                    System.out.print(" , ");
                System.out.print(parameterType.getSimpleName());
            }
            System.out.println(")");
        }
    }

源代码的下载链接
CSDN下载链接:http://download.csdn.net/detail/d_inosaur/9855095
码云链接:https://gitee.com/D_inasour/codes/ursvnom912cghatek7q3z89#Reflex.rar

你可能感兴趣的:(JAVA,反射)