171

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?

asked Jun 25, 2009 at 9:11

15 Answers 15

231

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));
}
user1079877
9,4185 gold badges45 silver badges55 bronze badges
answered Jun 25, 2009 at 9:17
3
  • 8
    Passing an mutable argument in and returning it probably isn't a great design. fields.addAll(type.getDeclaredFields()); would be more conventional than a enhanced for loop with add. Commented Jun 25, 2009 at 10:11
  • I'd feel the need to at least compile it (on stackoverflow!), and probably add in a little Arrays.asList. Commented Jun 25, 2009 at 10:34
  • It seems that your code collects all the fields, also private and static fields that are not inherited. Commented Feb 12, 2019 at 13:56
106
 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;
 }
answered Mar 9, 2010 at 0:15
3
  • 5
    Although I like very much recursivity (it's fun!), I prefer the readability of this method and the more intuitive parameters (not required a new collection to be pass), no more if (implicit in the for clause) and no iteration over fields themselves. Commented Sep 10, 2013 at 13:22
  • 1
    it shows recursive is unnecessary and.. I like short codes! thx! :) Commented Mar 4, 2015 at 8:08
  • 1
    In many years i always think the initial value in for is just an integer, with @Veera's question I think only recursive can solve it,@Esko Luontola your command is awesome. Commented Sep 9, 2017 at 10:20
46

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));
 }
}
answered May 28, 2014 at 15:27
0
10

You need to call:

Class.getSuperclass().getDeclaredFields()

Recursing up the inheritance hierarchy as necessary.

Burkhard
14.8k22 gold badges91 silver badges114 bronze badges
answered Jun 25, 2009 at 9:18
0
8

getFields(): Gets all the public fields up the entire class hierarchy and
getDeclaredFields(): Gets all the fields, regardless of their modifiers but only for the current class. So, you have to get for all the hierarchy involved.
I recently saw this code from org.apache.commons.lang3.reflect.FieldUtils

public static List<Field> getAllFieldsList(final Class<?> cls) {
 Validate.isTrue(cls != null, "The class must not be null");
 final List<Field> allFields = new ArrayList<>();
 Class<?> currentClass = cls;
 while (currentClass != null) {
 final Field[] declaredFields = currentClass.getDeclaredFields();
 Collections.addAll(allFields, declaredFields);
 currentClass = currentClass.getSuperclass();
 }
 return allFields;
}
answered Feb 1, 2019 at 21:53
1
  • 1
    Its better than best answer, because while cycle always faster than recursive calls. But i think LinkedList as data structure more suitable instead of ArrayList, because ArraysList will be resized (a few times), when size of list reaches capacity value, what will entail time costs Commented Mar 3, 2021 at 11:15
6

Use Reflections library:

public Set<Field> getAllFields(Class<?> aClass) {
 return org.reflections.ReflectionUtils.getAllFields(aClass);
}
answered Jun 10, 2016 at 10:23
6

With spring util library, you can use to check if one specific attribute exists into class:

Field field = ReflectionUtils.findRequiredField(YOUR_CLASS.class, "ATTRIBUTE_NAME");
log.info(field2.getName());

Api doc:
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/util/ReflectionUtils.html

or

 Field field2 = ReflectionUtils.findField(YOUR_CLASS.class, "ATTRIBUTE_NAME");
 log.info(field2.getName());

Api doc:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/ReflectionUtils.html

@cheers

answered May 5, 2020 at 12:34
5

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);
 }
}
answered Dec 22, 2011 at 0:16
3
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

answered Feb 17, 2011 at 21:51
2

You can try:

 Class parentClass = getClass().getSuperclass();
 if (parentClass != null) {
 parentClass.getDeclaredFields();
 }
answered Jun 25, 2009 at 9:18
2

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();
}
answered May 7, 2015 at 15:17
3
  • HI @Alexis LEGROS : ArrayUtils cannot find symbol. Commented Sep 9, 2017 at 0:29
  • 1
    This class is from Apache Commons Lang. Commented Sep 13, 2017 at 7:31
  • Apache already has a FieldUtils.getAllFields function to handle this question request. Commented Sep 13, 2017 at 9:23
1
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);
 }
}
answered Mar 9, 2010 at 0:06
1

This is a rewording of the accepted answer by @user1079877. It might that a version which does not modify a parameter of the function and also uses some modern Java features.

public <T> Field[] getFields(final Class<T> type, final Field... fields) {
 final Field[] items = Stream.of(type.getDeclaredFields(), fields).flatMap(Stream::of).toArray(Field[]::new);
 if (type.getSuperclass() == null) {
 return items;
 } else {
 return getFields(type.getSuperclass(), items);
 }
}

This implementation also makes invocation a bit more concise:

var fields = getFields(MyType.class);
answered Jan 19, 2019 at 21:36
1

There are a couple of quirks that aren't addressed by FieldUtils - specifically synthetic fields (eg injected by JaCoCo) and also the fact that an enum type of course has a field for each instance, and if you are traversing an object graph, getting all fields and then getting the fields of each of them etc, then you will get into an infinite loop when you hit an enum. An extended solution (and to be honest I'm sure this must live in a library somewhere!) would be:

/**
 * Return a list containing all declared fields and all inherited fields for the given input
 * (but avoiding any quirky enum fields and tool injected fields).
 */
public List<Field> getAllFields(Object input) {
 return getFieldsAndInheritedFields(new ArrayList<>(), input.getClass());
}
private List<Field> getFieldsAndInheritedFields(List<Field> fields, Class<?> inputType) {
 fields.addAll(getFilteredDeclaredFields(inputType));
 return inputType.getSuperclass() == null ? fields : getFieldsAndInheritedFields(fields, inputType.getSuperclass());
}
/**
 * Where the input is NOT an {@link Enum} type then get all declared fields except synthetic fields (ie instrumented
 * additional fields). Where the input IS an {@link Enum} type then also skip the fields that are all the
 * {@link Enum} instances as this would lead to an infinite loop if the user of this class is traversing
 * an object graph.
 */
private List<Field> getFilteredDeclaredFields(Class<?> inputType) {
 return Arrays.asList(inputType.getDeclaredFields()).stream()
 .filter(field -> !isAnEnum(inputType) ||
 (isAnEnum(inputType) && !isSameType(field, inputType)))
 .filter(field -> !field.isSynthetic())
 .collect(Collectors.toList());
}
private boolean isAnEnum(Class<?> type) {
 return Enum.class.isAssignableFrom(type);
}
private boolean isSameType(Field input, Class<?> ownerType) {
 return input.getType().equals(ownerType);
}

Test class in Spock (and Groovy adds synthetic fields):

class ReflectionUtilsSpec extends Specification {
 def "declared fields only"() {
 given: "an instance of a class that does not inherit any fields"
 def instance = new Superclass()
 when: "all fields are requested"
 def result = new ReflectionUtils().getAllFields(instance)
 then: "the fields declared by that instance's class are returned"
 result.size() == 1
 result.findAll { it.name in ['superThing'] }.size() == 1
 }
 def "inherited fields"() {
 given: "an instance of a class that inherits fields"
 def instance = new Subclass()
 when: "all fields are requested"
 def result = new ReflectionUtils().getAllFields(instance)
 then: "the fields declared by that instance's class and its superclasses are returned"
 result.size() == 2
 result.findAll { it.name in ['subThing', 'superThing'] }.size() == 2
 }
 def "no fields"() {
 given: "an instance of a class with no declared or inherited fields"
 def instance = new SuperDooperclass()
 when: "all fields are requested"
 def result = new ReflectionUtils().getAllFields(instance)
 then: "the fields declared by that instance's class and its superclasses are returned"
 result.size() == 0
 }
 def "enum"() {
 given: "an instance of an enum"
 def instance = Item.BIT
 when: "all fields are requested"
 def result = new ReflectionUtils().getAllFields(instance)
 then: "the fields declared by that instance's class and its superclasses are returned"
 result.size() == 3
 result.findAll { it.name == 'smallerItem' }.size() == 1
 }
 private class SuperDooperclass {
 }
 private class Superclass extends SuperDooperclass {
 private String superThing
 }
 private class Subclass extends Superclass {
 private String subThing
 }
 private enum Item {
 BIT("quark"), BOB("muon")
 Item(String smallerItem) {
 this.smallerItem = smallerItem
 }
 private String smallerItem
 }
}
answered Nov 21, 2019 at 9:33
1

I know this is a long overdue answer, but I just put here my answer just for my reference or anyone who is interested about an implementation without reflection as an extension of @dfa's answer;

public List<Field> getDeclaredFields(Class<?> tClass) {
 List<Field> fields = new LinkedList<>();
 while (tClass != null) {
 fields.addAll(Arrays.asList(tClass.getDeclaredFields()));
 tClass = tClass.getSuperclass();
 }
 return fields;
}
answered Apr 26, 2022 at 3:34

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.