obj.getClass()获取运行时真实类型,getDeclaredFields()返回该类显式声明的所有字段(含private),需setAccessible(true)才能读取私有值,且不包含父类字段,递归getSuperclass()可遍历继承链。

直接通过对象实例获取其真实 Class 类型,并结合 getDeclaredFields() 获取全部字段(含 private),是感知对象真实类信息与专有属性的核心路径。
用 getClass() 拿到最准确的运行时类型
编译期声明类型可能被向上转型掩盖,而 obj.getClass() 始终返回对象在堆中实际所属的类——哪怕它是子类或代理类。例如:
-
List<string> list = new ArrayList();</string>→list.getClass()返回ArrayList.class,不是List.class -
Service service = Proxy.newProxyInstance(...);→service.getClass()返回生成的代理类(如$Proxy1),而非接口类型
查全字段:getDeclaredFields() 是关键入口
getDeclaredFields() 返回当前类**显式声明**的所有字段,无论访问修饰符(private/protected/package-private/static/final),完全绕过继承链和可见性限制:
- 它不包含父类字段,确保你看到的是该类“自带”的专有属性
- 配合
field.getName()、field.getType()、field.getModifiers()可完整还原字段签名 - 若需追溯继承关系中的私有字段,需递归调用
getSuperclass().getDeclaredFields()
读取私有属性值:setAccessible(true) 不可省略
即使拿到了 private 字段对象,直接 field.get(obj) 仍会抛 IllegalAccessException。必须先解除 JVM 访问检查:
-
field.setAccessible(true);是临时开关,仅对当前 Field 实例生效,不影响其他反射调用或原类行为 - 对 final 字段,
setAccessible(true)允许读取,但写入需额外处理(如修改modifiers字段,不推荐) - 建议在 try-with-resources 或 finally 中恢复安全策略(尤其在受限环境如 Applet 或安全管理器启用时)
补充:识别专有属性的实用技巧
仅靠字段名和类型还不够,可进一步验证是否为“未公开专有属性”:
- 对比
getFields()结果 —— 若某字段不在其中,基本确认它未被设计为公共 API - 检查
isSynthetic()和isEnumConstant(),排除编译器生成字段(如 lambda 捕获变量、内部类引用) - 扫描注解:
field.getAnnotations()可发现框架标记(如@Transient、@JsonIgnore),辅助判断用途

















