Encontré una manera de obtener miembros heredados class.getDeclaredFields();
y acceso a miembros privados a través de class.getFields()
Pero estoy buscando campos heredados privados. ¿Cómo puedo conseguir esto?
Encontré una manera de obtener miembros heredados class.getDeclaredFields();
y acceso a miembros privados a través de class.getFields()
Pero estoy buscando campos heredados privados. ¿Cómo puedo conseguir esto?
Respuestas:
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 f = b.getClass().getSuperclass().getDeclaredField("i");
f.setAccessible(true);
System.out.println(f.get(b));
}
}
(O Class.getDeclaredFields
para una matriz de todos los campos).
Salida:
5
getSuperclass()
hasta llegar a null
si desea ir más alto.
getDeclaredFields()[0]
o getDeclaredField("i")
repite el [0]
acceso a la matriz en las siguientes dos declaraciones?
getDeclaredFields
. La respuesta se ha actualizado.
El mejor enfoque aquí es usar el Patrón de visitante para encontrar todos los campos de la clase y todas las superclases y ejecutar una acción de devolución de llamada en ellos.
Spring tiene una buena clase de utilidad ReflectionUtils
que hace precisamente eso: define un método para recorrer todos los campos de todas las superclases con una devolución de llamada:ReflectionUtils.doWithFields()
Invoque la devolución de llamada dada en todos los campos de la clase de destino, subiendo por la jerarquía de clases para obtener todos los campos declarados.
Parámetros:
- clazz - la clase de destino a analizar
- fc - la devolución de llamada a invocar para cada campo
- ff - el filtro que determina los campos a los que aplicar la devolución de llamada
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);
}
});
Encontrado campo booleano transitoria privada javax.management.relation.RoleUnresolvedList.typeSafe en la clase de tipo javax.management.relation.RoleUnresolvedList
encontrado ámbito privado transitoria booleano javax.management.relation.RoleUnresolvedList.tainted en javax.management.relation.RoleUnresolvedList clase de tipo de
terreno encontrado private transient 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
Campo encontrado protegido transitorio int java. util.AbstractList.modCount en la clase de tipo java.util.AbstractList
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 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;
}
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 esta respuesta)
De hecho, utilizo una jerarquía de tipos complejos, por lo que su solución no está completa. Necesito hacer una llamada recursiva para obtener todos los campos heredados privados. Aqui esta mi solucion
/**
* 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;
}
Necesitaba agregar soporte para campos heredados para planos en Model Citizen . Derivé este método que es un poco más conciso para recuperar los campos de una 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);
}