一:概述
Refliction反射重大意义在于通过运行时对象Class,针对运行时期的数据信息进行获取、修改等操作。不能正确理解以及操作反射,必然不能看懂框架源码。在最前面强调一下,例如getDeclaredFields()则表示获取自身所有属性,若无Declared如getFields()则表示获取继承自父类与自身所有public修饰的公共属性
二: Class运行时对象
Class对象是反射操作的入口,所有反射操作都可以说是建立在Class对象获取基础上进行的。通过Class对象可以获取到类修饰符、属性、方法、构造函数、内部类等
- 基本类型只能用隐藏属性class获取Class对象
- 八种基本类型的封装类都有一个TYPE常量储存Class对象
- Class提供的方法forName()参数为类完全限定路径,处理异常ClassNotFoundException
三:父类、内部类
Class对象可以获取到继承自父类、自身的内部类以及其继承的父类运行时对象,未直接继承父类默认Object。自身包含非public修饰内部类InnerClass,父类Object以及自身未声明public权限内部类,所以结果为0和1
- 继承父类通过方法getSuperClass(),默认父类Object
- 内部类通过方法getDeclaredClasses()、getClasses()。区别看第一节或示例代码注释
四:Modifiers修饰符
修饰符JDK中提供类Modifiers,比较难搞的是不论方法亦或是类的修饰符获取都是int类型返回值。int值来源于修饰符与整数一一对应相加后的和
4.1 修饰符获取
测试类TestPojo有public修饰符为1、方法testMethod使用public修饰也为1、属性name使用private修饰为2
4.2 权限修改
当对属性操作获取属性值、修改属性值,执行方法时如果权限控制不允许访问不修改其权限控制会抛出异常IllegalAccessException,修改访问权限使用方法setAccess()
五:Field属性
属性JDK中提供类Field,从下图该类属性可以看出当由Class对象获取到属性Field后,可以由该对象获取到属性名字、属性注解、属性值,当然也可以对属性进行赋值操作
5.1 Field对象获取
通过反射入口Class对象可以获取属性的集合与某个指定名称的属性。当然与获取内部类具备相似特点,获取继承自父类、自身public权限的属性亦或是自身所有权限类型的属性。上图示例代码中最后因为TestPojo中没有属性name,所以会抛出异常NoSuchFieldException
5.2 Field对象方法
通过Class对象对象获取到Field对象后可以执行系列属于属性对象的操作,如属性值赋值、属性值获取、属性权限修改、属性权限获取等操作。示例如下图所示
- 属性值操作都需要依赖具体对象,只有具体对象才具备属性值
- 如果属性修饰符非public,操作其属性值会抛出非法访问异常IllegalAccessException
六:Method方法
6.1 Method对象获取
- 获取某个确定方法对象需要方法名和方法参数的运行时对象。只有确定这两部分才能确定唯一方法,思考一下方法的重载就懂了
- 注意获取某个方法时若不具备该方法抛出异常NoSuchMethodException
- 方法参数为可变参就是用数组进行表示,可变参的底层实现最后也会转换为数组
6.2 方法参数
通过Method对象可以获取到方法的参数类型、数量。还有就是终极Boss获取参数对象Parameter数组
6.3 方法执行
方法执行需要确定方法所属对象并传入实参,当然如果方法没有参数则可以省略。还有一点就是方法的权限修饰很重要,当方法权限无法访问时一定要修改访问权限
七:Constructor构造器
7.1 Constructor对象获取
构造器对象的获取与方法对象类似,需要通过参数确定唯一构造器
7.2 实例化对象
通过构造函数进行对象实例化操作使用方法newInstance(),如果是带参构造函数则需要注入实参。当然如果构造函数访问权限不可访问则需要修改权限
八:注解
类、属性、方法以及方法参数对应类型都可以有注解,反射操作中也支持获取它们的注解进行判断操作
获取注解可以获取所有注解、某一类注解、某一个注解等等,获取到注解对象后还可以针对该对象获取到属性值等操作