Java反射无法直接访问父类private字段,因getDeclaredField()只查当前类声明字段,getField()仅查public字段;需递归遍历继承链调用getDeclaredField()并setAccessible(true)才能获取。
Java反射无法直接访问父类的private字段,因为getDeclaredField()只查找当前类声明的字段(不包含继承的),而getField()只找public字段(含继承的)。所以调用getDeclaredField("xxx")在子类上查父类private字段时,必然抛NoSuchFieldException。
需手动遍历类继承链,对每个类调用getDeclaredField(),直到找到目标字段或到达Object类。注意:即使字段是private,只要在某一级类中被声明,就能通过该类的getDeclaredField()获取到。
clazz.getDeclaredField(fieldName)
clazz.getSuperclass(),继续查找null(即已到Object),则字段不存在setAccessible(true)才能读写下面是一个通用工具方法,支持递归查找任意访问级别的字段(包括private、protected、包私有):
public static Field findField(Class<?> clazz, String fieldName) throws NoSuchFieldException { while (clazz != null) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); // 突破访问限制 return field; } catch (NoSuchFieldException e) { clazz = clazz.getSuperclass(); } } throw new NoSuchFieldException("Field '" + fieldName + "' not found in class hierarchy of " + clazz);}
假设Parent类定义了private String name,Child extends Parent,你想在Child实例上访问name:
立即学习“Java免费学习笔记(深入)”;
Child.class.getDeclaredField("name") → 报错findField(Child.class, "name") → 自动找到Parent中声明的字段Field后,用field.get(childInstance)即可读取值虽然技术上可行,但违背封装原则,且存在风险:
private字段可能被模块系统拒绝