Recuperando los nombres / valores heredados de los atributos usando Java Reflection

Tengo un objeto Java ‘ChildObj’ que se extiende desde ‘ParentObj’. Ahora, si es posible recuperar todos los nombres de atributos y valores de ChildObj, incluidos los atributos heredados también, utilizando el mecanismo de reflexión de Java?

Class.getFields me da la matriz de atributos públicos, y Class.getDeclaredFields me da la matriz de todos los campos, pero ninguno de ellos incluye la lista de campos heredados.

¿Hay alguna manera de recuperar los atributos heredados también?

no, debes escribirlo tú mismo. Es un método recursivo simple llamado en Class.getSuperClass () :

public static List getAllFields(List 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(), LinkedList.class)); } 
  public static List getAllFields(Class type) { List fields = new ArrayList(); for (Class c = type; c != null; c = c.getSuperclass()) { fields.addAll(Arrays.asList(c.getDeclaredFields())); } return fields; } 

Si, en cambio, deseabas confiar en una biblioteca para lograr esto, Apache Commons Lang versión 3.2+ proporciona 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 allFields = FieldUtils.getAllFieldsList(LinkedList.class); // Get the fields form each individual class in the type's hierarchy final List allFieldsClass = Arrays.asList(LinkedList.class.getFields()); final List allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields()); final List allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields()); final List 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)); } } 

Necesita llamar:

 Class.getSuperclass().getDeclaredFields() 

Recurriendo a la jerarquía de herencia según sea necesario.

Use la biblioteca Reflections:

 public Set getAllFields(Class aClass) { return org.reflections.ReflectionUtils.getAllFields(aClass); } 

Las soluciones recursivas están bien, el único problema pequeño es que devuelven un superconjunto de miembros declarados y heredados. Tenga en cuenta que el método getDeclaredFields () devuelve también métodos privados. Por lo tanto, dado que navega por toda la jerarquía de superclase, incluirá todos los campos privados declarados en las superclases, y no se heredarán.

Un filtro simple con un Modifier.isPublic || El predicado Modifier.isProtected haría:

 import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isProtected; (...) List inheritableFields = new ArrayList(); for (Field field : type.getDeclaredFields()) { if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) { inheritableFields.add(field); } } 
 private static void addDeclaredAndInheritedFields(Class c, Collection fields) { fields.addAll(Arrays.asList(c.getDeclaredFields())); Class superClass = c.getSuperclass(); if (superClass != null) { addDeclaredAndInheritedFields(superClass, fields); } } 

Versión de trabajo de la solución “DidYouMeanThatTomHa …” anterior

Puedes probar:

  Class parentClass = getClass().getSuperclass(); if (parentClass != null) { parentClass.getDeclaredFields(); } 

Más corto y con menos objetos instanciados? ^^

 private static Field[] getAllFields(Class type) { if (type.getSuperclass() != null) { return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields()); } return type.getDeclaredFields(); } 
 private static void addDeclaredAndInheritedFields(Class c, Collection fields) { fields.addAll(Arrays.asList(c.getDeclaredFields())); Class superClass = c.getSuperclass(); if (superClass != null) { addDeclaredAndInheritedFields(superClass, fields); } } 
Intereting Posts