反射是面向所有类的通用元编程能力,内省是专为JavaBean设计的属性级封装操作;前者操作字段/方法本体且可突破访问限制,后者通过getter/setter操作属性并遵守封装。

反射:面向所有类的通用元编程能力
反射(java.lang.reflect)是 Java 提供的一套底层机制,能在运行时动态获取任意类的结构信息(字段、方法、构造器、注解等),并执行操作——无论这个类是否符合 JavaBean 规范。
它不关心你有没有 getter/setter,也不要求你有无参构造;它可以:
- 获取私有字段并强制设值(
field.setAccessible(true)) - 调用私有方法或带参构造器
- 创建没有无参构造器的对象
- 绕过访问控制,甚至破坏封装性
典型场景:框架(Spring、MyBatis)、序列化工具、单元测试(Mockito)、JDBC 驱动加载(Class.forName("com.mysql.cj.jdbc.Driver"))。
内省:专为 JavaBean 设计的属性级封装操作
内省(java.beans.Introspector)本质是**基于反射的高层封装**,只针对严格遵循 JavaBean 规范的类(如:有 public 无参构造、属性有标准 getter/setter、属性名与方法名匹配)。
立即学习“Java免费学习笔记(深入)”;
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
它不操作字段本身,而是通过 PropertyDescriptor 找到对应的读写方法,再用反射去调用——也就是说,内省一定用反射,但反射不一定用内省。
它的行为天然受约束:
- 设置属性值,必须走
setXxx()方法(不能直接写字段) - 读取属性值,必须走
getXxx()或isXxx() - 若某属性没提供 setter,
getWriteMethod()返回 null,无法赋值 - 不支持操作私有字段、静态字段、非 JavaBean 属性(如 map 中的 key)
关键区别对比表(面试可脱口而出)
一句话总结:反射是“拆门撬锁进屋子”,内省是“敲门、按门铃、等主人开门后礼貌进门”。
- 作用范围:反射 → 全局任意类;内省 → 仅 JavaBean 类
- 操作对象:反射 → 字段/方法/构造器本体;内省 → 属性(property),即 getter/setter 封装后的逻辑单元
- 调用方式:反射 → 直接操作 Field/Method;内省 → 先得 PropertyDescriptor,再调其 getReadMethod()/getWriteMethod()
- 安全性:反射可突破访问限制;内省默认遵守封装,不越权
- 用途定位:反射用于框架底层、动态代理、泛型擦除补偿;内省多用于 BeanUtils、JSON 序列化、表单绑定等需属性映射的场景
面试加分点(简洁有力)
如果面试官追问“为什么还要有内省?反射不是啥都能干吗?”可以答:
- 内省提供了语义更清晰的“属性”抽象,屏蔽了 getter/setter 的细节,让代码更专注业务逻辑
- 它自动处理布尔类型 isXxx() 和 getXxx() 的兼容,反射要自己判断
- 框架如 Spring 的
BeanWrapper、Apache Commons BeanUtils 都基于内省,既安全又符合 JavaBean 约定 - 内省结果可缓存(
Introspector.getBeanInfo(Class)支持缓存),比反复反射查找更高效

















