反射的应用

反射概述

1. 反射(reflection)的概念是由Smith于1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗的讲就是反射可以在运行时根据执行的类名获得类的信息
2. Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
3. 想要解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
4. 反射是框架设计的灵魂(使用前提条件:必须先得到代表的字节码为Class,Class类用于表示.class文件(字节码))

通过反射获取Class实例的三种方式:

1. 对象.getClass()
2. 类名.class
3. Class.forName("全限定名")

Class<?> cls = Class.forName("demo1.Student");

  newInstance()  创建此Class对象所表示的类的一个新实例

Object newInstance = cls.newInstance("老三",18);    

第三种和前两种的区别:
  1.前两种必须明确类型
  2.第三种是你只要提供这种类型的字符串就行,这种扩展性更强,我不需要知道你的类,我只提供字符串,按照配置文件加载就可以了

通过反射获取接口和父类

1. 获取接口 getInterfaces()

Class<?>[] interfaces = cls.getInterfaces();

2. 获取父类 getSuperclass()

Class<?> superclass = cls.getSuperclass();

通过反射获取运行时类中构造

1. getConstructor(Class<?>... parameterType) 获取指定公共构造(包括父类)

Constructor<?> constructor = cls.getConstructor(String.class,int.class,String.class);

2. getConstructors() 获取本类的公共构造(包括父类)

Constructor<?>[] constructors = cls.getConstructors();

3. getDeclaredConstructor(Class<?>... parameterTypes) 获取本类指定的构造(共有或私有,但不包括父类)v

Constructor<?> con2 = cls.getDeclaredConstructor(String.class,int.class);

4. getDeclaredConstructors() 获取本类所有的构造(共有或私有,但不包括父类)

Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();

加Declared和不加Declared区别?
  加Declared可以获取本类所有的(包括私有,但不包括父类)东西,不加Declared获取本类以及父类公有的(不包括私有,但包括父类)东西
加s和不加s区别?
  加s获取的是多个,返回数组,不加s返回单个

通过反射获取运行时类中成员变量

getFields() 获取本类以及父类的所有公共属性(只能获取公有的)

Field[] fields2 = cls.getFields();
    for (Field field2 : fields2) {
        //获取访问修饰符
        int modifiers2 = field2.getModifiers();
        String string2 = Modifier.toString(modifiers2);
        //获取属性类型
        Class<?> type2 = field2.getType();
        String simpleName2 = type2.getSimpleName();
        //获取属性名称
        String name2 = field2.getName();
        //获取属性值
        Object object2 = field2.get(obj);
        System.out.println(string2+" "+simpleName2+" "+name2+" "+object2);
    }

getField(String name) 获取本类以及父类中指定的属性(只能获取公有的)

Field field2 = cls.getField("tName");

getDeclareFields() 获取本类以及父类的所有属性(包括私有)

    Field[] fields = cls.getDeclaredFields();
    //遍历属性
    for (Field field : fields) {
        field.setAccessible(true);
        //获取访问修饰符
        int modifiers = field.getModifiers();
        String string = Modifier.toString(modifiers);
        //获取属性类型
        Class<?> type = field.getType();
        String simpleName = type.getSimpleName();
        //获取属性名称
        String name = field.getName();
        //获取属性值
        Object value = field.get(obj);
        System.out.println(string+" "+simpleName+" "+name+" "+value);
        
        //设置属性值
        if("name".equals(name)) {
            field.set(obj, "阿莲");
        }else if("age".equals(name)) {
            field.set(obj, 17);
        }else if("love".equals(obj)) {
            field.set(obj, "喜欢老王");
        }
    }

getDeclareField(String name) 获取本类以及父类的指定属性(包括私有)

Field field = cls.getDeclaredField("name");

常用方法:

set(Object obj,Object value)
  第一个参数:指定对象
  

    if("name".equals(name)) {
        field.set(obj, "阿莲");
    }else if("age".equals(name)) {
        field.set(obj, 17);
    }else if("love".equals(obj)) {
        field.set(obj, "喜欢老王");
    }

get(Object obj) 返回指定对象上此Field表示的字段值
  参数:指定的对象

通过反射获取运行时类中成员方法

getDeclaredMethods() 获取本类所有的成员方法(包括私有)

Method[] methods = cls.getDeclaredMethods();
    //遍历方法
    for (Method method : methods) {
        //获取访问修饰符
        int modifiers = method.getModifiers();
        String string = Modifier.toString(modifiers);
        //获取返回值类型
        Class<?> type = method.getReturnType();
        String simpleName = type.getSimpleName();
        //获取方法名称
        String name = method.getName();
        //获取参数列表
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (Class<?> class1 : parameterTypes) {
            System.out.println(class1.getSimpleName());
        }
        System.out.println(string+" "+simpleName+" "+name);
        //调用方法
        //有个问题,在循环内部直接调用方法,那么每个方法都会执行,但是我们方法中的参数不一样,所以这个如果需要调用方法需判断
        if("setName".equals(name)) {
            //调用方法
            method.invoke(student, "老王");    //方法的对象,调用的参数
        }
    }
    System.out.println(student);

getDeclaredMethod(String name,Class<?>... parameterTypes) 获取本类指定的成员方法(包括私有)

Method method = cls.getDeclaredMethod("toString");

getMethods() 获取本类以及父类所有的公共成员方法(只能获取公有的)

Method[] methods2 = cls.getMethods();

getMethod(String name,Class<?>... parameterTypes) 获取本类以及父类指定的公共方法(只能获取公有的)

Method method2 = cls.getMethod("show", String.class);

invoke(Object obj,Object...args) 调用方法
  第一个参数:调用哪个对象的方法
  第二个参数:需要设置的值

    if("setName".equals(name)) {
                //调用方法
            method.invoke(student, "老王");    //方法的对象,调用的参数
        }

反射常用的方法

getName() 获取名称

    String name = method.getName();

getSimpleName() 获取简称

    Class<?> type = method.getReturnType();
    String simpleName = type.getSimpleName();

getModifiers() 获取访问修饰符

    int modifiers = method.getModifiers();
    String string = Modifier.toString(modifiers);

getParameterTypes() 获取参数列表

    Class<?>[] parameterTypes = method.getParameterTypes();
    for (Class<?> class1 : parameterTypes) {
            System.out.println(class1.getSimpleName());
        }
学习中,博客都是自己学习用的笔记,持续更新改正。。。
原文地址:https://www.cnblogs.com/Tunan-Ki/p/11681226.html