class.getfield只能获取当前类及其可访问父类中声明为public的字段,要求字段public且所在类对调用者可见;若父类package-private或字段非public,则抛nosuchfieldexception。

Class.getField 只能获取当前类及其**可访问的父类中声明为 public 的字段(不包括 private/protected,也不包括包级私有字段),且要求字段必须是 public 并且在继承链中可被当前类访问(即未被 package-private 阻断)。
getField 查找范围:public + 继承链可见
Java 的 getField(String name) 会沿类的继承链向上查找,但仅限于:
• 字段本身是 public;
• 该字段所在的类对调用者“可访问”——也就是说,如果父类是不同包中的非 public 类(如 package-private 类),即使它定义了 public 字段,getField 也查不到(因为父类不可见,其成员视为不可访问);
• 不查找 private 或 protected 字段(哪怕它们在父类中);
• 不查找包级访问权限(default)字段,哪怕在同一个包内。
常见失败场景与原因
以下情况调用 getField 会抛出 NoSuchFieldException:
- 字段是
protected或private—— 即使在父类中声明为 public,只要不是 public 就不行; - 字段在父类中是 public,但父类本身是
package-private(无修饰符)且与当前类不在同一包 —— 此时父类不可见,其 public 字段也不可被 getField 发现; - 字段名拼写错误或大小写不符(Java 区分大小写);
- 字段被子类“隐藏”(hiding)但未重写(static 字段不能被重写),不过 getField 仍按声明类型查找,不是运行时类型。
替代方案:getDeclaredField + 向上遍历
若需获取任意访问级别的字段(包括 protected、private),或确保覆盖整个继承链(含不可见父类),需手动遍历:
- 从目标 Class 开始,调用
getDeclaredField(name)尝试获取本类声明的字段(无视访问修饰符); - 若没找到,调用
getSuperclass()获取父类,重复上一步; - 直到
getSuperclass() == null(到达 Object)为止; - 注意:对 non-public 字段需调用
setAccessible(true)才能读写。
示例对比
假设:
// 同一包内class A { public int x = 1; }class B extends A { public int y = 2; }
则 B.class.getField("x") ✅ 成功(A 是 public 类,x 是 public);
但若 A 是 package-private:class A { public int x = 1; }(无 public 修饰符,且与 B 不同包)→ B.class.getField("x") ❌ 抛异常。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











