119

I found a way to get inherited members via class.getDeclaredFields(); and acces to private members via class.getFields() But i'm looking for private inherited fields. How can i achieve this?

Andreas Fester
36.7k9 gold badges101 silver badges125 bronze badges
asked Aug 25, 2010 at 15:11
3
  • 28
    "private inherited fields" does not exist. If a field is private, it is not inherited, and remains only to the scope of the parent class. To access parent private fields, you have to access parent class first (cf. aioobe's response) Commented Aug 25, 2010 at 15:22
  • 6
    that said, protected fields are inherited, but you have to do the same to get them by reflection. Commented Aug 25, 2010 at 16:14
  • Possible duplicate of Retrieving the inherited attribute names/values using Java Reflection Commented May 28, 2019 at 13:04

8 Answers 8

139

This should demonstrate how to solve it:

import java.lang.reflect.Field;
class Super {
 private int i = 5;
}
public class B extends Super {
 public static void main(String[] args) throws Exception {
 B b = new B();
 Field f = b.getClass().getSuperclass().getDeclaredField("i");
 f.setAccessible(true);
 System.out.println(f.get(b));
 }
}

(Or Class.getDeclaredFields for an array of all fields.)

Output:

5
answered Aug 25, 2010 at 15:14
4
  • Does this get all superclasses' fields or just the direct superclass? Commented May 14, 2019 at 16:28
  • Direct super classes' fields. You can recurse on getSuperclass() until you reach null if you want to go higher. Commented May 14, 2019 at 17:11
  • Why don't you use getDeclaredFields()[0] or getDeclaredField("i") but rather repeat the [0] array access in the next two statements? Commented Dec 3, 2019 at 15:41
  • It's due to the way this particular question is formulated. It was basically just a demonstration of how to use getDeclaredFields. Answer has been updated. Commented Dec 3, 2019 at 15:47
47

The best approach here is using the Visitor Pattern do find all fields in the class and all super classes and execute a callback action on them.


Implementation

Spring has a nice Utility class ReflectionUtils that does just that: it defines a method to loop over all fields of all super classes with a callback: ReflectionUtils.doWithFields()

Documentation:

Invoke the given callback on all fields in the target class, going up the class hierarchy to get all declared fields.

Parameters:
- clazz - the target class to analyze
- fc - the callback to invoke for each field
- ff - the filter that determines the fields to apply the callback to

Sample code:

ReflectionUtils.doWithFields(RoleUnresolvedList.class,
 new FieldCallback(){
 @Override
 public void doWith(final Field field) throws IllegalArgumentException,
 IllegalAccessException{
 System.out.println("Found field " + field + " in type "
 + field.getDeclaringClass());
 }
 },
 new FieldFilter(){
 @Override
 public boolean matches(final Field field){
 final int modifiers = field.getModifiers();
 // no static fields please
 return !Modifier.isStatic(modifiers);
 }
 });

Output:

Found field private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe in type class javax.management.relation.RoleUnresolvedList
Found field private transient boolean javax.management.relation.RoleUnresolvedList.tainted in type class javax.management.relation.RoleUnresolvedList
Found field private transient java.lang.Object[] java.util.ArrayList.elementData in type class java.util.ArrayList
Found field private int java.util.ArrayList.size in type class java.util.ArrayList
Found field protected transient int java.util.AbstractList.modCount in type class java.util.AbstractList

Felk
8,3042 gold badges41 silver badges78 bronze badges
answered Aug 25, 2010 at 16:11
5
  • 4
    that is not a "visitor pattern", but it is still a very nice tool if you have the Spring virus in your code. thanks for sharing it :) Commented Aug 28, 2013 at 0:27
  • 3
    @jose.diego I'm pretty sure you could argue about that. It visits a class hierarchy rather than an object tree, but the principle remains the same Commented Aug 28, 2013 at 14:43
  • Not sure if this comment will get a response, but you're only visiting a particular field at a time with this solution. If I need to look at other fields at the same time -- e.g., set this field to "abc" if another field is NULL -- I don't have the object as a whole available to me. Commented Nov 25, 2016 at 19:25
  • Its too bad that the JavaDoc for this class indicates that "it is only intended for internal use", so this is a possible risk to anyone who wishes to use it. Commented Jul 9, 2018 at 4:07
  • 1
    @spacemanspiff you're technically correct, but this class has been around for about 15 years (including 4 major release versions) and has widely been used by many Spring customers. I doubt they'll pull it back now. Commented Jul 9, 2018 at 16:31
38

This'll do it:

private List<Field> getInheritedPrivateFields(Class<?> type) {
 List<Field> result = new ArrayList<Field>();
 Class<?> i = type;
 while (i != null && i != Object.class) {
 Collections.addAll(result, i.getDeclaredFields());
 i = i.getSuperclass();
 }
 return result;
}

If you use a code coverage tool like EclEmma, you have to watch out: they add a hidden field to each of your classes. In the case of EclEmma, these fields are marked synthetic, and you can filter them out like this:

private List<Field> getInheritedPrivateFields(Class<?> type) {
 List<Field> result = new ArrayList<Field>();
 Class<?> i = type;
 while (i != null && i != Object.class) {
 for (Field field : i.getDeclaredFields()) {
 if (!field.isSynthetic()) {
 result.add(field);
 }
 }
 i = i.getSuperclass();
 }
 return result;
}
answered Aug 25, 2010 at 16:01
3
  • Thanks for your remark about synthetic fields, EMMA does the same. Commented May 22, 2012 at 9:04
  • this gets declared and inherited fields of the argument class so should be named getDeclaredAndInheritedPrivateFields. perfect though thanks! Commented Jan 7, 2013 at 19:58
  • 1
    nice catch on the isSynthetic :) Commented Nov 3, 2015 at 3:59
21
public static Field getField(Class<?> clazz, String fieldName) {
 Class<?> tmpClass = clazz;
 do {
 try {
 Field f = tmpClass.getDeclaredField(fieldName);
 return f;
 } catch (NoSuchFieldException e) {
 tmpClass = tmpClass.getSuperclass();
 }
 } while (tmpClass != null);
 throw new RuntimeException("Field '" + fieldName
 + "' not found on class " + clazz);
}

(based on this answer)

answered Apr 18, 2013 at 12:48
0
17

In fact i use a complex type hierachy so you solution is not complete. I need to make a recursive call to get all the private inherited fields. Here is my solution

 /**
 * Return the set of fields declared at all level of class hierachy
 */
public static List<Field> getAllFields(Class<?> clazz) {
 return getAllFieldsRec(clazz, new ArrayList<>());
}
private static List<Field> getAllFieldsRec(Class<?> clazz, List<Field> list) {
 Class<?> superClazz = clazz.getSuperclass();
 if (superClazz != null) {
 getAllFieldsRec(superClazz, list);
 }
 list.addAll(Arrays.asList(clazz.getDeclaredFields()));
 return list;
}
Lii
12.1k9 gold badges68 silver badges91 bronze badges
answered Aug 25, 2010 at 15:47
5
  • However, his solution did get you on the right path, didn't it? Commented Aug 25, 2010 at 15:55
  • 1
    Vector is bad old code. Please use a current data structure from the collections framework (ArrayList is adequate in most cases) Commented Aug 25, 2010 at 15:58
  • @aperkins the answer of aioobe look like mine, but i found it and then i saw the answer. @seanizer Vector is not that old, and it'a a member of the collection API Commented Aug 25, 2010 at 17:53
  • "As of the Java 2 platform v1.2, this class has been retrofitted to implement List, so that it becomes a part of Java's collection framework." retrofitted in 1.2? if that's not old then what is? Source: download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html Commented Aug 25, 2010 at 19:04
  • 8
    Vector has a huge overhead because everything is synchronized. And where you need synchronization, there are better classes in java.util.concurrent. Vector, Hashtable and StringBuffer should in most cases be replaced by ArrayList, HashMap and StringBuilder Commented Aug 25, 2010 at 19:09
8
private static Field getField(Class<?> clazz, String fieldName) {
 Class<?> tmpClass = clazz;
 do {
 for ( Field field : tmpClass.getDeclaredFields() ) {
 String candidateName = field.getName();
 if ( ! candidateName.equals(fieldName) ) {
 continue;
 }
 field.setAccessible(true);
 return field;
 }
 tmpClass = tmpClass.getSuperclass();
 } while ( clazz != null );
 throw new RuntimeException("Field '" + fieldName +
 "' not found on class " + clazz);
}
palacsint
28.9k11 gold badges85 silver badges112 bronze badges
answered Aug 27, 2010 at 14:29
8

I needed to add support for inherited fields for blueprints in Model Citizen. I derived this method that is a bit more concise for retrieving a Class' fields + inherited fields.

private List<Field> getAllFields(Class clazz) {
 List<Field> fields = new ArrayList<Field>();
 fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
 Class superClazz = clazz.getSuperclass();
 if(superClazz != null){
 fields.addAll(getAllFields(superClazz));
 }
 return fields;
}
answered Oct 9, 2013 at 16:34
0
-1

Commons Lang has the util method FieldUtils#getAllFieldsList for this.

answered Sep 7, 2022 at 9:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.