1、什么是反射?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象

2、使用反射

2.1、加载过程

反射就是把java类中的各种成分映射成一个个java对象,如图是类的正常加载过程:反射的原理在于class对象
Class对象的由来就是将字节码文件.class加载到内存中,并为之创建一个class对象
image.png

2.2、怎么使用反射?

一、获取 Class 对象的 3 种方法:

1、调用某个对象的getClass()方法

  1. Person p = new Person;
  2. Class c = p.getClass();

2、调用某个类的class属性来获取该类对应的class对象

  1. Class c = Person.class;

3、使用Class类中的forName()静态方法

  1. Class c = Class.forName("类的全路径");
  1. package fanshe;
  2. /**
  3. * 获取Class对象的三种方式
  4. * 1 Object ——> getClass();
  5. * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
  6. * 3 通过Class类的静态方法:forName(String className)(常用)
  7. *
  8. */
  9. public class Fanshe {
  10. public static void main(String[] args) {
  11. //第一种方式获取Class对象
  12. Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
  13. Class stuClass = stu1.getClass();//获取Class对象
  14. System.out.println(stuClass.getName());
  15. //第二种方式获取Class对象
  16. Class stuClass2 = Student.class;
  17. System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
  18. //第三种方式获取Class对象
  19. try {
  20. Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
  21. System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
  22. } catch (ClassNotFoundException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

注意:在运行期间,一个类只有一个Class对象产生。

二、通过反射获取构造方法

getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个

  1. Test test = new Test();
  2. Class c4 = test.getClass();
  3. Constructor[] constructors ;
  4. constructors = c4.getDeclaredConstructors();

getModifiers可以得到构造方法的类型
getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组
如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:

  1. for (int i = 0; i < constructors.length; i++) {
  2. System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");
  3. Class[] parametertypes = constructors[i].getParameterTypes();
  4. for (int j = 0; j < parametertypes.length; j++) {
  5. System.out.print(parametertypes[j].getName() + " ");
  6. }
  7. System.out.println("");
  8. }

getConstructors方法获取类中 所有的public类型的构造方法
getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。
获取无参构造方法直接不传参数

  1. try {
  2. constructors = c4.getDeclaredConstructor();
  3. System.out.print(Modifier.toString(constructors.getModifiers()) + );
  4. } catch (NoSuchMethodException e) {
  5. e.printStackTrace();
  6. }

获取有两个参数分别为int和String类型的构造方法

  1. Class[] p = {int.class,String.class};
  2. try {
  3. constructors = c4.getDeclaredConstructor(p);
  4. System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");
  5. Class[] parametertypes = constructors.getParameterTypes();
  6. for (int j = 0; j < parametertypes.length; j++) {
  7. System.out.print(parametertypes[j].getName() + " ");
  8. }
  9. } catch (NoSuchMethodException e) {
  10. e.printStackTrace();
  11. }

三、调用构造方法

主要借助于newInstance方法

   public Test(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("hello" + name + "i am" + age);
    }


    private Test(String name) {
        this.name = name;
        System.out.println("My Name is" +
                name);
    }

调用public方法

 Class[] p = {int.class,String.class};
 constructors = c4.getDeclaredConstructor(p);
 constructors.newInstance(24,"HuangLinqing");

调用私有构造方法呢,需要先设置constructors.setAccessible(true);

  Class[] p = {String.class};
  constructors = c4.getDeclaredConstructor(p);
  constructors.setAccessible(true);
  constructors.newInstance("HuangLinqing");

四、调用类的私有方法

getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型

Method method = c4.getDeclaredMethod("方法名",参数类型);

通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数

 method.invoke(test,"AAA");

五、获取类的私有字段并修改值

通过反射得到类的实例之后先获取字段

Field field = c4.getDeclaredField("name");
field.setAccessible(true);
field.set(o,"KOBE");

o是我们上面通过反射构造方法获取的实例
注意的是我们修改了name的值只对当前的实例对象有效

3、反射封装类

package jnidemo.hlq.com.hookdemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author Huanglinqing
 * @date 2019/4/28
 */

public class Reflex {

    /**
     * 获取无参构造函数
     * @param className
     * @return
     */
    public static Object createObject(String className) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};

        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取无参构造方法
     * @param clazz
     * @return
     */
    public static Object createObject(Class clazz) {
        Class[] pareTyple = new Class[]{};
        Object[] pareVaules = new Object[]{};

        return createObject(clazz, pareTyple, pareVaules);
    }

    /**
     * 获取一个参数的构造函数  已知className
     *
     * @param className
     * @param pareTyple
     * @param pareVaule
     * @return
     */
    public static Object createObject(String className, Class pareTyple, Object pareVaule) {

        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};

        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 获取单个参数的构造方法 已知类
     *
     * @param clazz
     * @param pareTyple
     * @param pareVaule
     * @return
     */
    public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};

        return createObject(clazz, pareTyples, pareVaules);
    }

    /**
     * 获取多个参数的构造方法 已知className
     * @param className
     * @param pareTyples
     * @param pareVaules
     * @return
     */
    public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class r = Class.forName(className);
            return createObject(r, pareTyples, pareVaules);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 获取构造方法
     *
     * @param clazz
     * @param pareTyples
     * @param pareVaules
     * @return
     */
    public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
        try {
            Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
            ctor.setAccessible(true);
            return ctor.newInstance(pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 获取多个参数的方法
     * @param obj
     * @param methodName
     * @param pareTyples
     * @param pareVaules
     * @return
     */
    public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
        if (obj == null) {
            return null;
        }

        try {
            //调用一个private方法 //在指定类中获取指定的方法
            Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
            method.setAccessible(true);
            return method.invoke(obj, pareVaules);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取一个参数的方法
     * @param obj
     * @param methodName
     * @param pareTyple
     * @param pareVaule
     * @return
     */
    public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = {pareTyple};
        Object[] pareVaules = {pareVaule};

        return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
    }

    /**
     * 获取无参方法
     * @param obj
     * @param methodName
     * @return
     */
    public static Object invokeInstanceMethod(Object obj, String methodName) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};

        return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
    }


    /**
     * 无参静态方法
     * @param className
     * @param method_name
     * @return
     */
    public static Object invokeStaticMethod(String className, String method_name) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};

        return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
    }

    /**
     * 获取一个参数的静态方法
     * @param className
     * @param method_name
     * @param pareTyple
     * @param pareVaule
     * @return
     */
    public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
        Class[] pareTyples = new Class[]{pareTyple};
        Object[] pareVaules = new Object[]{pareVaule};

        return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
    }

    /**
     * 获取多个参数的静态方法
     * @param className
     * @param method_name
     * @param pareTyples
     * @param pareVaules
     * @return
     */
    public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Class obj_class = Class.forName(className);
            return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 无参静态方法
     * @param method_name
     * @return
     */
    public static Object invokeStaticMethod(Class clazz, String method_name) {
        Class[] pareTyples = new Class[]{};
        Object[] pareVaules = new Object[]{};

        return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
    }

    /**
     * 一个参数静态方法
     * @param clazz
     * @param method_name
     * @param classType
     * @param pareVaule
     * @return
     */
    public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
        Class[] classTypes = new Class[]{classType};
        Object[] pareVaules = new Object[]{pareVaule};

        return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
    }

    /**
     * 多个参数的静态方法
     * @param clazz
     * @param method_name
     * @param pareTyples
     * @param pareVaules
     * @return
     */
    public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
        try {
            Method method = clazz.getDeclaredMethod(method_name, pareTyples);
            method.setAccessible(true);
            return method.invoke(null, pareVaules);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static Object getFieldObject(String className, Object obj, String filedName) {
        try {
            Class obj_class = Class.forName(className);
            return getFieldObject(obj_class, obj, filedName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Object getFieldObject(Class clazz, Object obj, String filedName) {
        try {
            Field field = clazz.getDeclaredField(filedName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
        try {
            Field field = clazz.getDeclaredField(filedName);
            field.setAccessible(true);
            field.set(obj, filedVaule);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
        try {
            Class obj_class = Class.forName(className);
            setFieldObject(obj_class, obj, filedName, filedVaule);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    public static Object getStaticFieldObject(String className, String filedName) {
        return getFieldObject(className, null, filedName);
    }

    public static Object getStaticFieldObject(Class clazz, String filedName) {
        return getFieldObject(clazz, null, filedName);
    }

    public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
        setFieldObject(classname, null, filedName, filedVaule);
    }

    public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
        setFieldObject(clazz, null, filedName, filedVaule);
    }
}