Доступ к частным унаследованным полям через отражение в Java
Я нашел способ получить унаследованные члены через class.getDeclaredFields();
и доступ к частным членам через class.getFields()
Но я ищу частные унаследованные поля.
Как я могу достичь этого?
7 ответов
Это должно продемонстрировать, как ее решить:
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));
}
}
выход:
5
лучший подход здесь-использование Шаблон Visitor найдите все поля в классе и все супер классы и выполните действие обратного вызова на них.
реализация
Spring имеет хороший класс полезности ReflectionUtils
это делает именно это: он определяет метод для цикла по всем полям всех супер классов с обратным вызовом:ReflectionUtils.doWithFields()
документы:
выполнение данного обратный вызов всех полей в целевом классе, поднимаясь по иерархии классов, чтобы получить все объявленные поля.
параметры:
- clazz-целевой класс для анализа
- fc-обратный вызов для вызова для каждого поля
- ff-фильтр, определяющий поля для применения обратного вызова к
пример кода:
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);
}
});
выход:
найдено поле private transient логическое пакета javax.управление.отношение.RoleUnresolvedList.typeSafe в типе класса javax.управление.отношение.RoleUnresolvedList
Найдено поле private transient boolean javax.управление.отношение.RoleUnresolvedList.испорчен в типе класса javax.управление.отношение.RoleUnresolvedList
Найдено поле private transient java.ленг.Объект [] java.утиль.список ArrayList.elementData в типе класса java.утиль.Коллекция ArrayList
Найдено поле private int java.утиль.список ArrayList.размер В тип класса Ява.утиль.Коллекция ArrayList
Найденное поле защищено переходным int java.утиль.AbstractList.modCount в типе класса java.утиль.AbstractList
это сделает это:
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;
}
Если вы используете инструмент покрытия кода, как EclEmma, вы должны следить: они добавить скрытое поле для каждого из ваших классов. В случае EclEmma эти поля помечены как синтетические, и вы можете фильтровать их так:
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);
}
(исходя из этой ответ)
на самом деле я использую иерархию сложного типа, поэтому ваше решение не завершено. Мне нужно сделать рекурсивный вызов, чтобы получить все частные унаследованные поля. Вот мое решение
/**
* 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;
}
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);
}
Мне нужно, чтобы добавить поддержку унаследованных полей для чертежей в Модель Гражданина. Я получил этот метод, который немного более лаконичен для извлечения полей класса + унаследованных полей.
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;
}