Given a class hierarchy, how do you reflectively read a private field that is declared on a superclass rather than the most-derived class?
answer
- getDeclaredField = this class only, any access
- getField = climbs hierarchy but public only
- Loop with getSuperclass() until null
- setAccessible(true) before field.get
- Module system can block setAccessible
basics
~10 sgetDeclaredField only looks at one class, so start at the subclass and walk up via getSuperclass() until you find the field. Then call setAccessible(true) before reading it.
solid answer
~30 sgetDeclaredField(name) only searches the exact class you call it on; it does not climb the hierarchy, and getField(name) won't help because the field is private. So you loop: start at the class, try getDeclaredField; on NoSuchFieldException move to getSuperclass() and try again, stopping when you find it or reach null (past Object). Once you have the Field, you call setAccessible(true) to bypass the access check (module/SecurityManager permitting), then field.get(instance) to read its value. This is exactly what libraries like Spring's ReflectionUtils.findField do — they encapsulate the upward walk so callers don't reimplement it.
code
java · 13 linesstatic Object readInheritedPrivate(Object target, String name)
throws ReflectiveOperationException {
for (Class<?> c = target.getClass(); c != null; c = c.getSuperclass()) {
try {
Field f = c.getDeclaredField(name); // this class only, any access
f.setAccessible(true); // override access check
return f.get(target);
} catch (NoSuchFieldException notHere) {
// keep climbing toward Object (getSuperclass() -> null ends it)
}
}
throw new NoSuchFieldException(name);
}go deeper
Knows that getDeclaredField only sees one class and that you must call setAccessible to read a private field.
Can write the getSuperclass() walk loop terminating at null and explain why getField won't reach a private inherited field.
Discusses module-system constraints on setAccessible, caching resolved Field objects, and prefers framework helpers / real APIs over hand-rolled access to internals.
Frames reflective access to private inherited state as a coupling/encapsulation risk, weighs JPMS strong-encapsulation impact on libraries, and designs alternatives (interfaces, serialization hooks, VarHandle) to avoid it.
## The problem In Java, **inheritance** means a subclass `B extends A` carries `A`'s data too. But the reflection lookup methods do not all search the same place: - **`getDeclaredField(name)`** searches **only the exact class** you invoke it on. It sees members of any visibility, but it does **not** look at superclasses. If the field lives on the parent, this throws `NoSuchFieldException`. - **`getField(name)`** *does* search up the hierarchy — but it only finds **public** members. A `private` field on the parent is invisible to it. So neither single call can directly fetch a **private, inherited** field. You must combine the upward search of `getField` with the all-access reach of `getDeclaredField` yourself. ## The hierarchy walk `Class` exposes its parent via **`getSuperclass()`**, which returns the parent `Class` object or **`null`** once you pass `Object` (Object's superclass is null). The algorithm: 1. Start with `c = startClass`. 2. Try `c.getDeclaredField(name)`. If it succeeds, you're done. 3. If it throws `NoSuchFieldException`, set `c = c.getSuperclass()`. 4. Repeat until found, or `c == null` (field doesn't exist anywhere). ## setAccessible — listing vs accessing Finding the `Field` object does **not** grant read access. Java still enforces the original access level when you call `field.get(...)`. To bypass that you call **`field.setAccessible(true)`**, which suppresses the access check. This can fail with `InaccessibleObjectException` under the Java **module system** (JPMS) if the declaring module hasn't `opens` the package, or be denied by a `SecurityManager` on older runtimes. After it succeeds, `field.get(instance)` returns the value (use the boxed type for primitives, or `getInt` etc.). ## Why not just use getField? `getField` is the right tool only when the target is **public**: it already walks supers and interfaces. The moment the field is non-public you fall back to the manual `getDeclaredField` + `getSuperclass` loop. ## Real-world note Frameworks hide this: Spring's `ReflectionUtils.findField`, Apache Commons `FieldUtils.getField(..., forceAccess)` do the upward walk and the `setAccessible` for you. Reaching into another class's private state is generally a smell (it couples you to internals that can change), so prefer a real API where one exists; reflection here is for frameworks, serializers, and tests. ## Performance Reflective lookups are comparatively expensive and walking the hierarchy repeats work. If you read the same field often, **cache** the resolved `Field` object (after `setAccessible`) rather than re-resolving each time.
- When would getField alone be sufficient, with no manual walk?When the target field is public — getField already searches superclasses and implemented interfaces for public members, so no manual loop is needed.
- What can make setAccessible(true) fail at runtime?The Java module system: if the declaring class's package isn't opened (via 'opens' or --add-opens) it throws InaccessibleObjectException; a SecurityManager could also deny it on older runtimes.
saying these in an interview costs you the question
- Assuming getDeclaredField searches superclasses
- Assuming getField can return a private inherited field
- Forgetting setAccessible and getting IllegalAccessException
- Ignoring that setAccessible can throw InaccessibleObjectException under JPMS