Day1 Java 反射

Java反射

DI的实现需要用到Java反射技术。

什么是反射?

反射:

  1. 没有通过new关键字直接创建对象;
  2. 根据类型元数据(包括类型的所有描述信息,如类名称、属性名称和属性类型、方法等),来间接地创建类对象,或调用类的方法;
  3. 可以动态地操作类;

类长什么样儿?
参见:https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-4.html#jvms-4.1

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

反射API

反射能做什么?

  1. 在运行时判断类型;
  2. 在运行时创建类对象;
  3. 在运行时判断类是否有某个成员变量或方法;
  4. 在运行时设置类属性值,或者调用对象的方法
  5. 动态代理
创建对象
  1. 获取类类型(类元数据信息),Class类型对象
    Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");
  2. 使用Class对象,获取构造函数,Constructor类型对象
    Constructor<?>[] constructors = cls.getDeclaredConstructors();
  3. 使用Constructor对象,创建目标对象
    User user = constructors[0].newInstance();

示例代码:

public class ConstructorTest {

    public static void main(String[] args) throws Exception {

        String className = "com.bailiban.day1.helloworld.model.User";

        // 1. 获取User的类类型(类元数据信息)
        Class<?> cls = Class.forName(className);

        // 2. 获取并遍历User所有构造函数
        System.out.println("--------获取并遍历User所有构造函数");
        Constructor<?>[] constructors = cls.getDeclaredConstructors();
        for (Constructor<?> cons: constructors) {
            // 获取限定符,这里全部是public
            String modifier = Modifier.toString(cons.getModifiers());
            System.out.print(modifier + " " + cls.getSimpleName() + "(");
            // 获取对应构造函数的参数类型和名称
            String paramStr = "";
            Parameter[] parameters = cons.getParameters();
            for (Parameter param: parameters) {
                paramStr += param.getType().getName() + " " + param.getName() + ", ";
            }
            if (!paramStr.equals(""))
                paramStr = paramStr.substring(0, paramStr.length()-2);
            System.out.println(paramStr + ");");
        }

        // 3. 通过无参构造函数,创建对象
        System.out.println("---------通过无参构造函数,创建对象");
        User user = (User) constructors[0].newInstance();
        user.setId(1001);
        user.setName("Jim");
        System.out.println(user);

        // 4. 通过有参构造函数,创建对象
        System.out.println("---------通过有参构造函数,创建对象");
        User user1 = (User) constructors[1].newInstance(1002, "David");
        System.out.println(user1);
    }
}

运行结果:

--------获取并遍历User所有构造函数
public User();
public User(int id, java.lang.String name);
---------通过无参构造函数,创建对象
User{id=1001, name='Jim'}
---------通过有参构造函数,创建对象
User{id=1002, name='David'}
设置属性值
  1. 获取类类型(类元数据信息),Class类型对象
    Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");
  2. 使用Class对象,获取成员变量,Field类型对象
    Field[] fields = cls.getDeclaredFields();
  3. 使用反射给属性赋值
Field field = cls.getDeclaredField("id");
field.setAccessible(true);
field.set(user, 1001);

示例代码:

public class FieldTest {

    public static void main(String[] args) throws Exception {

        // 1. 获取User的类类型(类元数据信息)
        Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");

        // 2. 根据Class对象获取User的成员变量
        System.out.println("-----User的成员变量:");
        Field[] fields = cls.getDeclaredFields();
        for (Field field: fields) {
            String modifier = Modifier.toString(field.getModifiers());
            System.out.println(modifier + " " + field.getType().getSimpleName() + " " + field.getName() + ";");
        }

        // 3. 使用反射给属性赋值
        System.out.println("-----使用反射给属性赋值:");
        User user = (User) cls.getConstructors()[0].newInstance();
        Field field = cls.getDeclaredField("id");
        field.setAccessible(true);
        field.set(user, 1001);
        field = cls.getDeclaredField("name");
        field.setAccessible(true);
        field.set(user, "Jim");
        System.out.println(user);
    }
}

运行结果:

-----User的成员变量:
private int id;
private String name;
-----使用反射给属性赋值:
User{id=1001, name='Jim'}
调用方法
  1. 获取类类型(类元数据信息),Class类型对象
    Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");
  2. 使用Class对象,获取对象方法,Method类型对象
    Method[] methods = cls.getDeclaredMethods();
  3. 使用反射调用方法
Method method = cls.getDeclaredMethod("setId", int.class);
method.invoke(user, 1001);

示例代码:

public class MethodTest {

    public static void main(String[] args) throws Exception {

        // 1. 获取User的类类型(类元数据信息)
        Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");

        // 2. 根据Class对象获取User的方法
        System.out.println("-----User的方法:");
        Method[] methods = cls.getDeclaredMethods();
        for (Method method: methods) {
            String modifier = Modifier.toString(method.getModifiers());
            System.out.print(modifier + " " + method.getName() + "(");
            // 获取对应构造函数的参数类型和名称
            String paramStr = "";
            Parameter[] parameters = method.getParameters();
            for (Parameter param: parameters) {
                paramStr += param.getType().getSimpleName() + " " + param.getName() + ", ";
            }
            if (!paramStr.equals(""))
                paramStr = paramStr.substring(0, paramStr.length()-2);
            System.out.println(paramStr + ");");
        }

        // 3. 使用反射调用方法
        System.out.println("-----使用反射调用方法:");
        User user = (User) cls.getConstructors()[0].newInstance();
        Method method = cls.getDeclaredMethod("setId", int.class);
        method.invoke(user, 1001);
        method = cls.getDeclaredMethod("setName", String.class);
        method.invoke(user, "Jim");
        System.out.println(user);
    }
}

运行结果:

-----User的方法:
public toString();
public getName();
public getId();
public setName(String name);
public setId(int id);
-----使用反射调用方法:
User{id=1001, name='Jim'}
posted @ 2019-12-16 21:36  cheng_18  阅读(233)  评论(0)    收藏  举报