una reflexion principio por obtener metodo method invocar ejemplos clase atributos java reflection inheritance private-members

principio - reflexion java ejemplos



Acceso a campos privados heredados a través de la reflexión en Java (7)

Encontré una manera de obtener miembros heredados a través de class.getDeclaredFields(); y acceso a miembros privados a través de class.getFields() Pero estoy buscando campos privados heredados. ¿Cómo puedo conseguir esto?


De hecho, utilizo una jerarquía de tipo complejo para que su solución no esté completa. Necesito hacer una llamada recursiva para obtener todos los campos privados heredados. Aquí está mi solución

/** * Return the set of fields declared at all level of class hierachy */ public Vector<Field> getAllFields(Class clazz) { return getAllFieldsRec(clazz, new Vector<Field>()); } private Vector<Field> getAllFieldsRec(Class clazz, Vector<Field> vector) { Class superClazz = clazz.getSuperclass(); if(superClazz != null){ getAllFieldsRec(superClazz, vector); } vector.addAll(toVector(clazz.getDeclaredFields())); return vector; }


El mejor enfoque aquí es usar el Patrón de visitante , encontrar todos los campos en la clase y todas las superclases y ejecutar una acción de devolución de llamada sobre ellos.

Implementación

Spring tiene una buena clase de utilidad ReflectionUtils que hace precisamente eso: define un método para recorrer todos los campos de todas las súper clases con una devolución de llamada: ReflectionUtils.doWithFields()

Documentación:

Invoca la devolución de llamada dada en todos los campos de la clase objetivo, subiendo por la jerarquía de clases para obtener todos los campos declarados.

Parámetros:
- clazz - la clase objetivo para analizar
- fc - la devolución de llamada a invocar para cada campo
- ff - el filtro que determina los campos para aplicar la devolución de llamada a

Código de muestra:

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); } });

Salida:

Campo encontrado private booleano transitorio javax.management.relation.RoleUnresolvedList.typeSafe en la clase de tipo javax.management.relation.RoleUnresolvedList
Campo encontrado privado booleano transitorio javax.management.relation.RoleUnresolvedList.tainted in tipo clase javax.management.relation.RoleUnresolvedList
Transitorio privado privado encontrado java.lang.Object [] java.util.ArrayList.elementData en la clase de tipo java.util.ArrayList
Campo encontrado private int java.util.ArrayList.size en la clase de tipo java.util.ArrayList
Transient protegido del campo encontrado int int java.util.AbstractList.modCount en la clase de tipo java.util.AbstractList


Esto debería demostrar cómo resolverlo:

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[] fs = b.getClass().getSuperclass().getDeclaredFields(); fs[0].setAccessible(true); System.out.println(fs[0].get(b)); } }

Salida:

5


Esto lo hará:

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; }

Si usa una herramienta de cobertura de código como EclEmma , debe tener cuidado: agregan un campo oculto a cada una de sus clases. En el caso de EclEmma, ​​estos campos están marcados como sintéticos , y usted puede filtrarlos así:

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; }


Necesitaba agregar soporte para campos heredados para planos en Model Citizen . Obtuve este método que es un poco más conciso para recuperar campos de clase + campos heredados.

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; }


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); }


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); }

(basado en this respuesta)