Demo04.java 5.0 KB

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