class.getdeclaredfields()可获取本类所有声明字段(含private),但需调用setaccessible(true)才能访问其值;它不包含继承字段,访问父类private字段需递归getsuperclass()。

Class.getDeclaredFields() 本身就能获取包括 private 在内的所有本类声明的字段(不包含继承的),无需额外条件。关键在于它返回的是 Field[] 数组,每个 Field 默认受 Java 访问控制限制——即使拿到了 private 字段对象,直接调用 get() 或 set() 会抛 IllegalAccessException。所以“获取”分两步:拿到字段引用 + 破除访问限制。
一、获取所有 private 字段(含本类声明的)
该方法只返回当前类中显式定义的字段,不管访问修饰符(public/protected/private),但不包含父类或接口中的字段。
- 若目标类是
User,且它有一个private String name;,则User.class.getDeclaredFields()会包含这个name字段 - 若
User继承自Person,而Person里有private int age;,那么getDeclaredFields()不会返回age(需用getSuperclass().getDeclaredFields()向上递归)
二、访问 private 字段值必须调用 setAccessible(true)
拿到 Field 对象后,要读写其值,必须绕过访问检查:
-
field.setAccessible(true);—— 这是关键一步,否则field.get(obj)抛异常 - 该操作仅影响当前
Field实例,不影响 JVM 其他地方的安全策略 - JDK 9+ 在模块化环境下可能受限(如未开放对应包),需配置
--add-opens参数
三、完整示例(获取并读取 private 字段)
假设类:
class User {
private String name = "Alice";
private int id = 101;
}
获取并打印所有 private 字段值:
User user = new User();
for (Field f : User.class.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true); // 开放访问
}
System.out.println(f.getName() + " = " + f.get(user));
}
// 输出:name = Alice,id = 101
四、注意继承字段和性能开销
如果需要所有字段(含父类 private 字段),得手动遍历继承链:
- 从当前类开始,循环调用
clazz.getDeclaredFields(),再clazz = clazz.getSuperclass(),直到clazz == null或到达Object -
setAccessible(true)有一定反射开销,频繁调用建议缓存已设为可访问的Field对象 - 生产环境慎用,尤其涉及安全敏感场景(如金融、权限校验)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











