Java 反射

Java 的反射机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。

这种动态获取程序信息以及动态调用对象的功能称为 Java 语言的反射机制。反射被视为动态语言的关键。

反射的作用

  1. 在运行时判断任意一个对象所属的类。
  2. 在运行时构造任意一个类的对象。
  3. 在运行时判断任意一个类所具有的成员变量和方法。
  4. 在运行时调用任意一个对象的方法。
  5. 生成动态代理。

反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。

通过反射操作类

要想剖解一个类,必须先要获取到该类的字节码文件对象。而剖解使用的就是 Class 类中的方法。所以先要获取到每一个字节码文件对应的 Class 类型的对象。

// 获取到Person的类类型对象
// 1. 通过类获取类类型对象
Class c1 = Person.class;
// 2. 通过字符串(完整类路径)获取到类类型对象
Class c2 = Class.forName("com.dailyblue.java.reflection.Person");
// 3. 通过对象获取到当前对象的类类型对象
Person p = new Person();
Class c3 = p.getClass();
// 4. 只有8大原始类型的封装类有这个方法
Class c4 = Integer.TYPE;

三种获取类对象方式

Java 反射_第1张图片

Class 类的常见方法

Java 反射_第2张图片

通过反射操作对象

通过刚才的方式,我们获取到了类的类型对象(字节码文件对象),下来我们需要进一步通过这个类的类型对象获取到该类的实例对象。

        // 1. 获取类
        Class c = Class.forName("com.dailyblue.java.reflection.Person");
        // 2.1 获取Person类的对象
        Person p1 = new Person();
        Person p2 = new Person(1);
        // 2.2 通过反射获取Person类的对象
        // 获取到Person类的所有构造器
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor c1 : constructors) {
            System.out.println(c1);
        }
        System.out.println("----------------------------------------------------------");
        // 获取到具体某个构造器
        Class[] 形式参数列表 = {};
        Constructor con1 = c.getDeclaredConstructor(形式参数列表);
        Constructor con2 = c.getDeclaredConstructor(Integer.class);
        Constructor con3 = c.getDeclaredConstructor(Integer.class, String.class);
        System.out.println(con1);
        System.out.println(con2);
        System.out.println(con3);
        System.out.println("----------------------------------------------------------");
        // 通过构造器获取类的对象
        Object obj1 = con1.newInstance();
        Object obj2 = con2.newInstance(3);
        Object obj3 = con3.newInstance(4, "admin");
        System.out.println(obj1);
        System.out.println(obj2);
        System.out.println(obj3);

通过反射操作属性

我们已经获取到类的字节码对象,也通过字节码对象获取到该类的实例对象。下来我们来看看如何操纵类中的属性。

Field 类概述

Field 类代表某个类中的一个成员变量。 Field 完整类名为 java.lang.reflect.Field,它提供类或接口中单独字段的信息,以及对单独字段的动态访问。

Field 类的常见方法

Java 反射_第3张图片

相关代码 

        Class c = Class.forName("com.dailyblue.java.reflection.Student");
        Object obj = c.getDeclaredConstructor().newInstance();
        // 获取所有属性
        // 获取所有定义的属性
        Field[] fields1 = c.getDeclaredFields();
        // 获取所有拥有的public属性(包含继承下来的)
        Field[] fields2 = c.getFields();
        // 在所定义的属性中查找指定名称的属性
        Field f1 = c.getDeclaredField("no");
        Field f2 = c.getDeclaredField("schoolName");
        // 在所拥有的public属性中查找指定名称的属性
        Field f3 = c.getField("name");
        System.out.println("---------------------------------------");
        // 给属性赋值
        f1.setAccessible(true); // 设置私有属性可以访问
        f1.set(obj,1);
        f2.set(obj,"西北大学");
        System.out.println("---------------------------------------");
        // 获取属性的值
        Object v1 = f1.get(obj);
        Object v2 = f2.get(obj);

通过反射操作方法

Method 类的概述

Method 的方法提供了对于在类或接口中单个方法的信息和访问,反射方法可能是一个类方法或实体方法(包含抽象方法)。

Method 类的常见方法

Java 反射_第4张图片

相关代码

        // 获取类
        Class c = Class.forName("com.dailyblue.java.reflection.Student");
        // 获取对象
        Object obj = c.getDeclaredConstructor().newInstance();
        // 获取所有方法
        Method[] methods1 = c.getDeclaredMethods();
        Method[] methods2 = c.getMethods();
        System.out.println("---------------------------------");
        // 获取单个方法 第一个参数是方法名,其后参数是形式参数列表
        Method m1 = c.getDeclaredMethod("e", String.class);
        Method m2 = c.getDeclaredMethod("f");
        Method m3 = c.getMethod("d", Integer.TYPE, String.class);
        System.out.println("---------------------------------");
        // 操作方法 第一个参数是对象,其后参数是实际参数列表
        Object result1 = m1.invoke(obj, "admin");
        m2.setAccessible(true);
        Object result2 = m2.invoke(obj);
        Object result3 = m3.invoke(obj, 1, "张三");
invoke方法:

作用:调用包装在当前Method对象中的方法。
原型:Object invoke(Object obj,Object...args) 
参数解释:obj:实例化后的对象;args:用于方法调用的参数
返回:根据obj和args调用的方法的返回值
抛出错误:IllegalAccessException(Method对象强制Java语言执行控制或无权访问obj对象) IllegalArgumentException(方法是实例化方法,而指定需要调用的对象并不是实例化后的类或接口)

你可能感兴趣的:(Java,基础,java)