反射是通用底层运行时元数据操作,可访问任意类的全部结构并绕过访问控制;内省是基于反射、专为JavaBean属性设计的封装层,仅识别符合命名规范的getter/setter方法。

反射和内省不是同一层次的概念,也不是互斥关系——内省是建立在反射之上的、面向 JavaBean 的专用工具,而反射是更底层、更通用的运行时操作能力。
反射:通用的运行时元数据操作
反射让你能在运行时获取任意类的完整结构信息,并动态调用其成员。它不关心你是不是 JavaBean,也不依赖 getter/setter 命名规则。
- 能拿到类的构造器、所有字段(包括 private)、全部方法(含静态/私有)、注解、泛型信息等
- 可直接读写字段值(哪怕 private),无需方法支持;也可绕过访问控制(setAccessible(true))
- 典型用途:框架加载配置类、JSON 序列化库解析对象、单元测试模拟私有状态
- 核心 API 在 java.lang.reflect 包下(Class、Field、Method、Constructor 等)
内省:专为 JavaBean 属性设计的封装层
内省只关注符合 JavaBean 规范的类,它的目标很明确:自动识别并操作以 get/set 开头的属性访问方法,把字段“包装”成逻辑属性。
- 默认只识别 public 的 getter/setter 方法,且严格遵循命名约定(如 getName() ↔ name 属性)
- 不直接操作字段,而是通过 PropertyDescriptor 获取对应的方法,再用反射调用它们
- 自动过滤掉非属性方法(比如普通业务方法、无配对的 getter 或 setter)
- 核心 API 在 java.beans 包下(Introspector、PropertyDescriptor、BeanInfo)
关键区别一目了然
假设有个类:
private String name;
public String getName() { return name; }
public void setName(String n) { name = n; }
public void doSomething() { ... }
- 反射能看到 name 字段、getName/setName/doSomething 三个方法,还能直接修改 name 字段值
- 内省只把 getName/setName 当作一个属性(name),doSomething 被忽略,原始字段 name 不暴露也不参与
- 内省底层确实用了反射,但它屏蔽了细节,只暴露“属性”这一抽象概念
什么时候该用哪个?
- 需要通用、底层控制(比如序列化、AOP、动态代理)→ 选反射
- 只是想安全、规范地读写 Bean 属性(如表单绑定、配置映射、DTO 转换)→ 优先用内省,或更便捷的 BeanUtils
- 遇到非标准类(无 getter/setter、字段 public、方法命名不规范)→ 内省可能失效,必须退回反射


















