Ho trovato un modo per ottenere membri ereditati tramite class.getDeclaredFields();
e accedere a membri privati tramite class.getFields()
Ma sto cercando campi ereditati privati. Come posso raggiungere questo obiettivo?
Ho trovato un modo per ottenere membri ereditati tramite class.getDeclaredFields();
e accedere a membri privati tramite class.getFields()
Ma sto cercando campi ereditati privati. Come posso raggiungere questo obiettivo?
Risposte:
Questo dovrebbe dimostrare come risolverlo:
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
per un array di tutti i campi.)
Produzione:
5
getSuperclass()
fino a raggiungere null
se vuoi andare più in alto.
getDeclaredFields()[0]
o getDeclaredField("i")
piuttosto ripeti l' [0]
accesso all'array nelle prossime due istruzioni?
getDeclaredFields
. La risposta è stata aggiornata.
L'approccio migliore qui è usare il Visitor Pattern per trovare tutti i campi nella classe e tutte le super classi ed eseguire un'azione di callback su di essi.
Spring ha una bella classe Utility ReflectionUtils
che fa proprio questo: definisce un metodo per eseguire il ciclo su tutti i campi di tutte le super classi con un callback:ReflectionUtils.doWithFields()
Richiama la richiamata data su tutti i campi nella classe di destinazione, risalendo la gerarchia delle classi per ottenere tutti i campi dichiarati.
Parametri:
- clazz - la classe di destinazione da analizzare
- fc - il callback da invocare per ogni campo
- ff - il filtro che determina i campi a cui applicare il callback
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);
}
});
Trovato campo booleano transitorio privato javax.management.relation.RoleUnresolvedList.typeSafe nella classe di tipo javax.management.relation.RoleUnresolvedList
Trovato campo booleano transitorio privato javax.management.relation.RoleUnresolvedList.tainted nella classe di tipo javax.management
campo FoundRole.Role. private transient java.lang.Object [] java.util.ArrayList.elementData nel tipo class java.util.ArrayList
Trovato campo private int java.util.ArrayList.size nel tipo class java.util.ArrayList
Trovato campo protetto transient int java. util.AbstractList.modCount nella classe di tipo java.util.AbstractList
Questo lo farà:
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;
}
Se usi uno strumento di copertura del codice come EclEmma , devi stare attento: aggiungono un campo nascosto a ciascuna delle tue classi. Nel caso di EclEmma, questi campi sono contrassegnati come sintetici e puoi filtrarli in questo modo:
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);
}
(basato su questa risposta)
In effetti uso una gerarchia di tipi complessa, quindi la soluzione non è completa. Devo effettuare una chiamata ricorsiva per ottenere tutti i campi ereditati privati. Ecco la mia soluzione
/**
* 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;
}
Avevo bisogno di aggiungere il supporto per i campi ereditati per i progetti in Model Citizen . Ho derivato questo metodo che è un po 'più conciso per recuperare i campi di una classe + i campi ereditati.
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);
}