| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- package course;
- import java.lang.reflect.Constructor;
- /**
- * @author WanJl
- * @version 1.0
- * @title Demo04
- * @description 反射
- * @create 2026/8/12
- */
- public class Demo04 {
- /*
- 反射
- 是Java语言提供的一种【运行时动态机制】,他允许程序在【运行的状态】中:
- 对 任意一个类 都能获取这个类的所有属性和方法(包括私有的成员private)
- 对 任意一个对象 都能够调用它的任意属性和方法。
- 这种 动态获取类的信息 + 动态调用对象方法 的功能 就是Java的反射机制。
- 普通的调用 反射调用 的区别:
- 获取类信息的时机:
- 普通调用(编译期)- 就是在编译器写死,代码写死。
- 反射调用(运行期)- 运行时才会动态获取
- 依赖关系:
- 普通调用(编译期)- 编译期强耦合,耦合度高
- 反射调用(运行期)- 运行时才管理,解耦
- 创建对象:
- 普通调用(编译期)- new 类名()
- 反射调用(运行期)- Class.forname() + newInstance()
- 调用方法:
- 普通调用(编译期)- 对象.方法名()
- 反射调用(运行期)- method对象.invoke(对象,参数)
- 灵活性方面:
- 普通调用(编译期)- 固定不变
- 反射调用(运行期)- 高度灵活,可以动态切换
- 一句话:普通方式是代码写死的,反射方式是动态的。反射是Java中各种框架的基础——Spring、MyBatis、Hibernate、JDBC驱动加载等等都离不开反射。
- 为什么需要反射?
- 如果没有反射,我们的程序需要使用某个类,就必须在编译期就要知道它的名字,然后使用new创建对象,使用. 调用方法。
- 这些在很多真实的场景中无法满足需求:
- 1、配置驱动:比如某个框架需要读取配置文件,文件里面写的时候字符串类型的类名,框架在运行的时候才会拿到这个字符串,
- 并且需要通过反射才能够把它翻译成真实的类并且进行实例化。
- 2、通用工具:写一个能够打印任意对象的全部属性的通用工具,调用方法后传入什么参数不确定,那么就只能通过反射来实现。
- 3、第三方类库的解耦:比如我们使用某个类库,Java只需要定义这个类库的规则(接口),类库自己实现具体的操作,
- 然后通过反射,在运行时动态加载,源码里面根本就不需要依赖某个具体的类。
- 注意:我们需要学习反射,目的是1、学习框架的时候帮助我们理解框架的底层源码。2、当我们进行架构设计、开发中间件程序的时候需要使用反射做解耦和通用适配。
- 至于日常的业务开发中,一定一定一定尽量不要使用反射。开发使用反射,就相当于玩游戏使用金手指(开挂)
- 1、使用反射可能破坏封装性
- 2、使用反射的效率要远比正常创建对象效率低的多,最低3~100倍
- 反射的工作机制:
- Java程序运行的时候,.class字节码文件会被类加载器(ClassLoader)加载进JVM(Java虚拟机),JVM会为每一个类创建
- 唯一的一个 java.lang.Class 对象。这个对象就是 “类的类模板”,里面记录类这个类的全部信息(类名、父类、接口、字段属性、方法、构造方法等等)
- 反射的一切操作,都是从这个Class对象出发的。拿到了Class之后,可以依次获取它的构造方法对象(Constructor)、方法对象(Method)、属性对象(Field)
- 再通过这些对象去创建这个类的实例对象,读写字段属性,调用方法...
- Person.java源码 --javac编译--> Person.class字节码 --类加载器(ClassLoader)加载-->Person的Class对象(类的类模板)
- 通过Person的Class对象
- |-获取Person类的 构造方法对象Constructor --> newInstance()创建Person对象
- |-获取Person类的 字段属性对象Field -->get/set 读写字段属性变量
- |-获取Person类的 方法对象Method -->invoke()执行方法
- 反射涉及到的核心类:
- Class 类 java.lang.Class 表示一个类的模板,是反射的入口
- Constructor 构造方法 java.lang.reflect.Constructor 表示一个构造方法,可以创建对象
- Field 字段属性 java.lang.reflect.Field 表示一个成员变量,可以读写字段属性
- Method 方法 java.lang.reflect.Method 表示一个成员方法,可以调用方法
- Modifier 修饰符 java.lang.reflect.Modifier 解析修饰符(public/private/static等等)
- Parameter 参数 java.lang.reflect.Modifier 代表的是方法参数
- */
- public void printUtil(Object obj){
- //输出这个类的所有属性名---就必须要使用反射来实现
- }
- }
|