Retrieving the inherited attribute names/values using Java Reflection

0 votes
asked Jun 25, 2009 by veera

I've a Java object 'ChildObj' which is extended from 'ParentObj'. Now, if it is possible to retrieve all the attribute names and values of ChildObj, including the inherited attributes too, using Java reflection mechanism?

Class.getFields gives me the array of public attributes, and Class.getDeclaredFields gives me the array of all fields, but none of them includes the inherited fields list.

Is there any way to retrieve the inherited attributes also?

10 Answers

0 votes
answered Jun 25, 2009 by dfa

no, you need to write it yourself. It is a simple recursive method called on Class.getSuperClass():

public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
    fields.addAll(Arrays.asList(type.getDeclaredFields()));

    if (type.getSuperclass() != null) {
        getAllFields(fields, type.getSuperclass());
    }

    return fields;
}

@Test
public void getLinkedListFields() {
    System.out.println(getAllFields(new LinkedList<Field>(), LinkedList.class));
}
0 votes
answered Jun 25, 2009 by manuel-selva

You can try:

   Class parentClass = getClass().getSuperclass();
   if (parentClass != null) {
      parentClass.getDeclaredFields();
   }
0 votes
answered Jun 25, 2009 by nick-holt

You need to call:

Class.getSuperclass().getDeclaredFields()

Recursing up the inheritance hierarchy as necessary.

0 votes
answered Jun 9, 2010 by didyoumeanthattomhaw
private static void addDeclaredAndInheritedFields(Class c, Collection<Field> fields) {
    fields.addAll(Arrays.asList(c.getDeclaredFields()));
    Class superClass = c.getSuperclass();
    if (superClass != null) {
        addDeclaredAndInheritedFields(superClass, fields);
    }
}
0 votes
answered Jun 9, 2010 by esko-luontola
    public static List<Field> getAllFields(Class<?> type) {
        List<Field> fields = new ArrayList<Field>();
        for (Class<?> c = type; c != null; c = c.getSuperclass()) {
            fields.addAll(Arrays.asList(c.getDeclaredFields()));
        }
        return fields;
    }
0 votes
answered Jun 17, 2011 by theo-platt
private static void addDeclaredAndInheritedFields(Class<?> c, Collection<Field> fields) {
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class<?> superClass = c.getSuperclass(); 
    if (superClass != null) { 
        addDeclaredAndInheritedFields(superClass, fields); 
    }       
}

Working version of "DidYouMeanThatTomHa..." solution above

0 votes
answered Jun 22, 2011 by marek-dec

The recursive solutions are OK, the only small issue is that they return a superset of declared and inherited members. Note that getDeclaredFields() method returns also private methods. So given that you navigate the whole superclass hierarchy you will include all private fields declared in the superclasses, and those don't get inherited.

A simple filter with a Modifier.isPublic || Modifier.isProtected predicate would do:

import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isProtected;

(...)

List<Field> inheritableFields = new ArrayList<Field>();
for (Field field : type.getDeclaredFields()) {
    if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) {
       inheritableFields.add(field);
    }
}
0 votes
answered Jun 28, 2014 by chris

If instead you wanted to rely upon a library to accomplish this, Apache Commons Lang version 3.2+ provides FieldUtils.getAllFieldsList:

import java.lang.reflect.Field;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.AbstractSequentialList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.junit.Assert;
import org.junit.Test;

public class FieldUtilsTest {

    @Test
    public void testGetAllFieldsList() {

        // Get all fields in this class and all of its parents
        final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class);

        // Get the fields form each individual class in the type's hierarchy
        final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields());
        final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields());
        final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields());
        final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields());

        // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
        Assert.assertTrue(allFields.containsAll(allFieldsClass));
        Assert.assertTrue(allFields.containsAll(allFieldsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent));
    }
}
0 votes
answered Jun 7, 2015 by alexis-legros

Shorter and with less object instantiated ? ^^

private static Field[] getAllFields(Class<?> type) {
    if (type.getSuperclass() != null) {
        return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields());
    }
    return type.getDeclaredFields();
}
0 votes
answered Jun 10, 2016 by lukasz-ochmanski

Use Reflections library:

public Set<Field> getAllFields(Class<?> aClass) {
    return org.reflections.ReflectionUtils.getAllFields(aClass);
}
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...