答案是:获取Class对象、创建对象、调用方法/访问字段。面试90%围绕这三步:1. 通过User.class/obj.getClass()/Class.forName()获取Class;2. 用getDeclaredConstructor().setAccessible(true).newInstance()创建对象;3. 通过getDeclaredMethod()/getDeclaredField()配合setAccessible(true)和invoke()/get()/set()操作成员。

直接看核心脉络,别从头啃文档。
先抓三个关键动作
面试问反射,90%围绕“怎么拿到类信息、怎么造对象、怎么调方法”这三件事。其他都是在这基础上加限制或变体。
-
获取 Class 对象:记住三种方式——
User.class(最常用、最快)、obj.getClass()(有实例时用)、Class.forName("com.xxx.User")(配置驱动、动态加载场景) -
创建对象:不用
clazz.newInstance()(已废弃),改用getDeclaredConstructor().setAccessible(true).newInstance(...);私有构造也能走通 -
调用方法/读写字段:先
getDeclaredMethod("xxx", ...)或getDeclaredField("xxx"),再setAccessible(true),最后invoke()或get()/set()
重点盯住“访问控制”这个坑
面试官最爱在这里设卡:为什么 private 方法能被调用?setAccessible(true) 真的万能吗?
- 它绕过 JVM 的访问检查,但不等于绕过所有安全机制(比如 SecurityManager 启用时会拦截)
- 修改
final static字段可能无效——编译器已内联常量值,反射改的是内存地址,不影响已编译的字节码引用 - Java 9+ 模块系统下,如果模块没导出包,
setAccessible可能抛InaccessibleObjectException
性能和场景必须拎得清
别只背“反射慢”,要说清楚慢在哪、怎么缓解、什么情况下值得用。
立即学习“Java免费学习笔记(深入)”;
- 慢在:每次调用都要解析符号引用、做权限校验、类型转换,比直接调用多十几倍开销
- 优化思路:缓存
Method/Field对象(比如 Spring 就这么干),避免重复查找 - 典型场景:框架层(Spring IOC、MyBatis 参数绑定)、通用工具类(JSON 序列化)、测试私有逻辑、插件热加载
顺手记两个高频变形题
这些不是附加题,是反射能力的试金石。
-
往
ArrayList<Integer>里加 String:利用泛型擦除,通过反射拿到add方法并传入 String,JVM 不做泛型检查 -
判断类是否带某个注解:
clazz.isAnnotationPresent(Transactional.class)或clazz.getAnnotation(Transactional.class),这是 AOP 和事务管理的基础


















