什么是Java反射
- 反射reflection是在运行时动态访问类与对象的技术
- 反射是JDK1.2版本后的高级特性,隶属于
java.lang.reflect
- 他将对象的创建时机从原本的编译时创建延迟到运行时创建
- 大多数Java框架都基于反射实现参数配置,动态注入等特性
1 | Scanner in = new Scanner(System.in); |
反射的核心类
- Class
- Constructor
- Method
- Field
Class类
- Class是JVM中代表
类和接口
的类 - Class对象具体包含了某个特定类的结构信息
- 通过Class类可以获取对应类的构造方法,方法,成员变量
Class核心方法
- Class.forName() - 静态方法,用于获取指定Class对象
- classObj.newInstance() - 通过默认构造方法创建新的对象 (在Java9之后被deprecated)
- classObj.getConstructor() - 获取指定的public修饰构造方法Constructor对象
- classObj.getMethod() - 获取指定的public修饰方法Method对象
- classObj.getField() - 获取指定的public修饰的成员变量Field对象
1 | // 将Employee类加载到JVM,并返回对应Class对象 |
创建Class对象时可能抛出的异常
- InstantiationException
- 实例化异常,对象无法被实例化
- 例如abstract抽象对象
- IllegalAccessException
- 非法访问,在作用域外访问对象构造方法或成员变量
- 例如尝试访问私有构造方法
Constructor类
- 对Java类中的构造方法的抽象
- Constructor对象包含了具体类的某个具体构造方法的声明
- 通过Constructor对象调用带参构造方法创建对象
Constructor类的核心方法
-
classObj.getConstructor() - 获取指定public修饰的构造方法对象
-
constructorObj.newInstance() - 通过对应的构造方法创建对象
-
例子,在通过Class对象创建Constructor对象时,需要提供每一个参数的Class类
-
在Constructor对象创建Employee对象时,需要传入每一个参数
1 | Class employeeClass = Class.forName("entity.Employee"); |
创建Constructor对象时可能抛出的异常
- InstantiationException
- 实例化异常,对象无法被实例化
- 例如abstract抽象对象
- IllegalAccessException
- 非法访问,在作用域外访问对象构造方法或成员变量
- 例如尝试访问私有构造方法
- InvocationTargetException
- 当被调用的方法内部抛出了异常而没有被捕获时
- NoSuchMethodException
- 没有找到与之对应的构造方法
Method类
- Method对象指代某个类中的方法的描述
- Method对象使用classObj.getMethod()方法获取
- 通过Method对象调用指定对象的对应方法
Method类核心方法
- classObj.getMethod() - 获取指定public修饰的方法的对象
- methodObj.invoke() - 调用指定对象的对应方法
1 | Class employeeClass = Class.forName("entity.Employee"); |
Field类
- 对应某个具体类中成员变量的声明
- Field对象使用classObj.getField()方法获取
- 通过Field对象可为某对象成员变量赋值/取值
Field类核心方法
- classObj.getField() - 获取指定public修饰的成员变量对象
- fieldObj.set() - 为某对象指定成员变量赋值
- fieldObj.get() - 获取某对象指定成员变量数值
Field可能抛出的异常
- NoSuchFieldException
- 没有找到对应的Field
- 当尝试访问private的Field时也会抛出这个异常
1 | Class employeeClass = Class.forName("entity.Employee"); |
getDeclared。。。系列方法
- 之前的方法只能获取public对象
- getDeclared。。系列方法可以获取非作用域内的构造方法,方法,成员变量 (private)
例子,如果我们想获取当前对象的所有成员变量的值
- 不管是private还是public,我们需要用到getDeclaredFields()
1 | Class employeeClass = Class.forName("entity.Employee"); |
反射在项目中的应用
- 切换网站的语言
- 根据不用的设备切换网站layout
- 不需要重新编译或者改变已有代码