java反射本质是运行时动态操作类的能力,核心路径为:获取class对象(.class、getclass()、forname)、创建对象、调用方法、访问私有成员;需理解性能开销、优化手段及与注解协同工作的机制。

Java 反射核心大纲面试题,本质是围绕“运行时动态操作类”这一能力展开的系统性考察。查法不是靠死记硬背题库,而是抓住反射的逻辑主线——从“怎么拿到类信息”到“怎么用这些信息做事”,再延伸到“为什么这么设计、有什么代价”。下面直接按真实面试高频路径梳理:
获取 Class 对象的三种方式及区别
这是所有反射操作的起点,必问。
-
类名.class:编译期已知类型,安全、高效,推荐用于框架内部或工具类中明确类型的场景 -
对象.getClass():已有实例时使用,注意它返回的是实际运行时类型(可能和声明类型不同) -
Class.forName("全限定类名"):字符串加载,支持动态类名(如 JDBC 加载驱动),会触发类初始化(执行 static 块)
⚠️ 注意:
getClass()和instanceof不等价——前者精确匹配实际类,后者允许子类匹配;面试常考这个细节。
如何通过反射创建对象、调用方法、访问私有成员
这三步构成反射最典型的操作链:
- 创建对象:优先用
getDeclaredConstructor().setAccessible(true).newInstance(...),避免已过时的clazz.newInstance() - 调用方法:
getMethod()只能找 public 方法(含父类继承的);getDeclaredMethod()才能拿到 private 方法,调用前必须setAccessible(true) - 访问字段:
getDeclaredField("xxx")+setAccessible(true)+field.set(obj, value)或field.get(obj)
✅ 关键点:
setAccessible(true)是突破 Java 访问控制的核心开关,但仅在 SecurityManager 未启用时生效;JDK 9+ 模块系统下需额外--add-opens参数。
反射为什么慢?怎么优化?
性能问题是高频追问点。
- 慢的原因:绕过 JVM 编译期优化(如内联)、每次调用都要做权限检查、类型转换和参数封装开销大
- 优化手段:
- 缓存
Class、Method、Field对象(比如用ConcurrentHashMap存起来) - 避免重复
setAccessible(true),设一次即可 - 在 JDK 16+ 可考虑
VarHandle或MethodHandle替代部分反射场景(更轻量、更安全)
- 缓存
反射和注解的关系
注解本身不执行逻辑,它只是元数据;真正读取并响应注解的是反射。
-
@Retention(RetentionPolicy.RUNTIME)是前提(只有 RUNTIME 级别才能被反射读取) - 通过
clazz.isAnnotationPresent(...)、method.getAnnotation(...)、field.getAnnotations()等 API 提取注解信息 - Spring 的
@Autowired、MyBatis 的@Select都依赖这套机制完成自动装配或 SQL 绑定
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











