java反射核心在于理清“运行时类信息怎么来、怎么拿、怎么用”三条主线,以class对象为唯一入口,区分三种获取方式本质,掌握field/constructor/method的可见性控制与调用机制,并理解其jvm底层原理及典型应用场景。

Java 反射深度复习,关键不在“背API”,而在理清三条主线:运行时类信息怎么来、怎么拿、怎么用。掌握这三点,框架源码读得懂,面试不卡壳,写通用工具也不慌。
紧扣 Class 对象:反射唯一的入口
所有反射操作都始于一个 Class 对象——它不是你 new 出来的实例,而是 JVM 在类加载时自动创建的元数据容器,每个类有且仅有一个。复习时重点区分三种获取方式的本质差异:
- 类名.class:编译期绑定,不触发类初始化(静态块不执行),最安全高效,适合工具类或已知类型场景
- 对象.getClass():依赖已有实例,返回实际运行时类型(支持多态,比如子类对象返回子类 Class),适合类型推断
- Class.forName("全限定名"):字符串驱动,会触发类的初始化(静态代码块执行),是 Spring 等框架动态加载 Bean 的核心手段
拆解三大核心 API:字段、构造器、方法
拿到 Class 后,真正干活的是 Field、Constructor、Method 这三类对象。复习时注意它们的“可见性”和“访问控制”逻辑:
- getFields() / getMethods() 只返回 public 成员(含继承的);getDeclaredXXX() 返回本类声明的所有成员(含 private),但默认不可访问
- 调用私有成员前必须调用 setAccessible(true),这是绕过 Java 访问检查的开关,也是反射破坏封装性的体现
- Constructor.newInstance() 和 Method.invoke() 都可能抛出 InvocationTargetException,真实异常被包装在其中,需用 getCause() 提取
直击底层原理:不只是 API 调用
理解反射为什么慢、为什么能突破 private,要看到 JVM 层面的动作:
- Class 对象里缓存了 Method/Field 的根信息,每次 getMethod() 创建的新 Method 实例共享同一个底层 MethodAccessor
- 首次 invoke 会生成并加载一个 NativeMethodAccessorImpl 或 GeneratedMethodAccessor(字节码增强),后续调用才真正快起来
- 反射调用比直接调用慢,主因是取消了 JIT 内联优化、多了参数校验与安全检查,不是“语法糖”而是实打实的运行时解析
结合真实场景反向验证
脱离场景的反射是空中楼阁。复习时用几个典型例子串起知识点:
- 手写简易 ORM:通过注解 + 反射读取字段名 → 拼 SQL → setAccessible 给 private 字段赋值
- 模拟 Spring Bean 初始化:Class.forName 加载类 → getDeclaredConstructor().newInstance() 创建实例 → getMethod("setXxx").invoke() 注入依赖
- 通用 JSON 反序列化:根据字段类型匹配构造器 → 用 Field.set() 填充对象 → 处理嵌套对象递归反射
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











