What is the difference between getFields and getDeclaredFields in Java reflection
I'm a little confused about the difference between the getFields
method and the getDeclaredFields
method when using Java reflection.
I read that getDeclaredFields
gives you access to all the fields of the class and that getFields
only returns public fields. If this is the case, why wouldn't you just always use getDeclaredFields
?
Can someone please elaborate on this, and explain the difference between the two methods, and when/why you would want to use one over the other?
Solution 1:
getFields()
All the public
fields up the entire class hierarchy.
getDeclaredFields()
All the fields, regardless of their accessibility but only for the current class, not any base classes that the current class might be inheriting from.
To get all the fields up the hierarchy, I have written the following function:
public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass,
@Nullable Class<?> exclusiveParent) {
List<Field> currentClassFields = Lists.newArrayList(startClass.getDeclaredFields());
Class<?> parentClass = startClass.getSuperclass();
if (parentClass != null &&
(exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) {
List<Field> parentClassFields =
(List<Field>) getFieldsUpTo(parentClass, exclusiveParent);
currentClassFields.addAll(parentClassFields);
}
return currentClassFields;
}
The exclusiveParent
class is provided to prevent the retrieval of fields from Object
. It may be null
if you DO want the Object
fields.
To clarify, Lists.newArrayList
comes from Guava.
Update
FYI, the above code is published on GitHub in my LibEx project in ReflectionUtils.
Solution 2:
As already mentioned, Class.getDeclaredField(String)
only looks at the fields from the Class
in which you call it.
If you want to search a Field
in the Class
hierarchy, you can use this simple function:
/**
* Returns the first {@link Field} in the hierarchy for the specified name
*/
public static Field getField(Class<?> clazz, String name) {
Field field = null;
while (clazz != null && field == null) {
try {
field = clazz.getDeclaredField(name);
} catch (Exception e) {
}
clazz = clazz.getSuperclass();
}
return field;
}
This is useful to find a private
field from a superclass, for example. Also, if you want to modify its value, you can use it like this:
/**
* Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name
*/
public static void setField(Object object, String fieldName, Object value) throws Exception {
Field field = getField(object.getClass(), fieldName);
field.setAccessible(true);
field.set(object, value);
}