Java反射机制

68 阅读2分钟

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

反射

反射是指对于任何一个 Class 类,在运行的时候 都可直接得到这个类的全部成分。

在运行时,可以直接得到这个类的构造器对象:Constructor

在运行时,可以直接得到这个类的成员变量对象:Field

在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力 称为Java语言的反射机制。

  • 反射获取类对象
public static void main(String[] args) throws Exception {
    // class类中的静态方法
    Class<?> c = Class.forName("com.Review.day12.d2_getClass.Student");  // forName(权限名:包名+类名)
    System.out.println(c);  // class com.Review.day12.d2_getClass.Student

    // 类名.class
    Class<Student> c1 = Student.class;

    // 对象.getClass() 获取对象对应类的class对象
    Student s = new Student();
    System.out.println(s.getClass());
}
  • 反射获取构造器对象
// getConstructor 不能拿私有的 只能拿 public修饰的
@Test
public void getConstructor() throws Exception {
    // 获取类对象
    Class c = Student.class;
    // 提取类的全部构造器  用数组装[2]
    Constructor[] Constructor = c.getConstructors();

    // 遍历构造器
    for (java.lang.reflect.Constructor constructor : Constructor) {
        // constructor.getParameterCount() 获取参数个数
        System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
    }
}
// getDeclaredConstructors  私有的也可以拿
// getConstructor  获取public修饰的某个构造器  -- 定位单个
// getDeclaredConstructor 获取某个构造器(无论私有还是公开) - 定位单个  - 常用

******暴力破解
    // 获取类对象
    Class c = Student.class;
    Constructor cons = c.getDeclaredConstructor();
	// 如果遇到了私有的构造器,可以暴力反射 - 我理解为暂时破坏单例设计模式
	cons.setAccessible(true)  // 权限暂时被打开
	// 接着就可以通过 私用的构造器创建对象了
    Student s = (Student) cons.newInstance();
  • 反射获取成员变量对象
    public static void main(String[] args) {
        // 获取Class对象
        Class c = Student.class;
        // 定位全部成员变量
        Field[] fields = c.getDeclaredFields();

        // 遍历
        for (Field field : fields) {
            // field.getType() 获取类型
            System.out.println(field.getName() + "====>" + field.getType()); // name====>class java.lang.String

        }
    }
    // getDeclareField  根据名称定位某个成员变量
	// 成员变量同样可以进行 暴力破解
  • 反射获取方法对象
    public static void main(String[] args) {
        // 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
        // class类中用于获取成员方法的方法。
        Class c = Student.class;

        // 获得类中的所有成员方法对象,返回数组,只获得本类中申明的方法。
        Method[] dcl = c.getDeclaredMethods();

        for (Method method : dcl) {
            System.out.println(method.getName() + "   返回值类型" + method.getReturnType() +
                    "   参数个数:" + method.getParameterCount());
        }
    }
    // 提取单个方法对象 getDeclaredMethod
  • 反射的作用 - 泛型擦除
    public static void main(String[] args) throws Exception {
        // 声明两个字典
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();

        System.out.println(list1.getClass());
        System.out.println(list2.getClass());

        System.out.println(list1.getClass() == list2.getClass());

        System.out.println("__________________");

        ArrayList list3 = list2;   // 这种也是一种泛型擦除
        list1.add(1);
        list1.add(2);
        list1.add(3);

        Class c = list1.getClass();

        // 定义c类中的add方法
        Method add = c.getDeclaredMethod("add", Object.class);

        Object laity = add.invoke(list1, "laity");

        System.out.println(laity);

        System.out.println(list1);  // [1, 2, 3, laity]
    }