反射主要用于框架底层而非业务代码,如Spring Bean初始化、MyBatis字段映射、JUnit测试执行和Jackson序列化;业务中滥用会引发性能、封装与模块访问问题。
反射常用于框架底层,不是业务代码的常规选择
Java反射机制的核心价值不在日常开发,而在Spring、MyBatis、JUnit这类框架内部。它让框架能在运行时动态加载类、调用方法、访问私有字段——而这些操作在编译期完全不可知。
如果你在业务逻辑里频繁写或,大概率设计出了问题。
反射带来性能开销、破坏封装、绕过编译检查,还可能被模块系统(Java 9+)限制访问。
哪些场景下框架必须用反射
框架需要“对未知类型做统一处理”,这是反射不可替代的典型场景:
Spring Bean 初始化
:读取
注解后,用
实例化类,而非硬
编码
new
MyBatis 结果集映射
:执行
查询后,通过
+
把数据库列值塞进目标对象私有字段
JUnit 5 测试发现与执行
:扫描所有含
的 public 方法,用
运行,不依赖测试类继承特定父类
JSON 序列化(如 Jackson)
:对任意 POJO 调用
获取全部字段,再结合
读取值
面试常问的反射性能与替代方案
面试官问“反射慢在哪”,不是让你背 JVM 源码,而是看是否理解关键瓶颈:
和
触发类加载和元数据解析,开销大——应缓存
对象,避免重复查找
默认走委派逻辑,JDK 7 后对 public 方法做了优化,但仍有安全检查开销;可调用
跳过访问控制(注意模块限制)
真正高频调用场景(如 RPC 参数序列化),主流方案已转向
(更轻量)或代码生成(如 ByteBuddy、Javassist 编译期织入)
示例:缓存 Method 避免重复查找
elasticsearch-9.4.0 win
PHP中文网提供Elasticsearch 9.4.0 Windows 版本压缩包下载解压即用,内置 OpenJDK 无需额外配置 Java 环境。该版本重磅推出原生 Prometheus 支持、正式版 Elastic Workflows 以及基于 NVIDIA cuVS 的 GPU 加速向量索引,大幅提升 AI 检索与可观测性能力。建议前往官网下载,快速体验极速搜索与强大的数据分析功能。
下载
立即学习
“
Java免费学习笔记(深入)
”;
模块系统(Java 9+)下反射容易被静默失败
如果项目用了
,默认禁止反射访问其他模块的非导出包,
会直接抛
,而不是早期的 IllegalAccessException。
解决方式不是关模块系统,而是显式在
中开放:
启动参数也可临时放宽:
(仅调试用)
Maven 插件(如 maven-compiler-plugin)需设
为 8 或更低,否则编译器会拒绝生成反射相关
字节
码
这个限制在 Spring Boot 2.6+ 和 JDK 17 合体时踩坑最多——看似一样的反射代码,换环境就崩,根源常在这里。
Class.forName()Method.invoke()@ComponentClass.getDeclaredConstructor().newInstance()ResultSetclazz.getDeclaredField("id")field.setAccessible(true)@Testmethod.invoke(testInstance)getDeclaredFields()field.get(obj)Class.forName()getDeclaredMethod()MethodMethod.invoke()setAccessible(true)MethodHandleprivate static final Map METHOD_CACHE = new ConcurrentHashMap<>();
public static Object invokeGetter(Object obj, String fieldName) throws Exception {
String key = obj.getClass().getName() + "." + fieldName;
Method method = METHOD_CACHE.computeIfAbsent(key, k -> {
try {
return obj.getClass().getMethod("get" + capitalize(fieldName));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
});
return method.invoke(obj);
} module-info.javasetAccessible(true)InaccessibleObjectExceptionmodule-info.javaopens com.example.model to java.base;--add-opens java.base/java.lang=ALL-UNNAMEDrelease