#java #reflection
#java #отражение
Вопрос:
Я пытаюсь получить поля и значения первого родителя моего объекта. Мой текущий код таков:
Class<? extends Object> cls = obj.getClass();
Field[] fields = cls.getDeclaredFields();
for ( Field field : fields )
{
String fieldName = field.getName();
String fieldValue = field.get(obj);
}
Моя структура классов похожа на эту:
class A
{
int x;
}
class B extends A
{
int y;
}
class C extends B
{
int z;
}
Теперь я передаю объект C в метод, и я хочу получить все поля из C и B, но не из A. Есть ли способ сделать это (используя отражение, я не хочу внедрять другие методы)?
Ответ №1:
Лучиан, используй метод getSuperclass() для получения ссылки на объект класса, который представляет тип суперкласса рассматриваемого объекта. После этого вам будет легко получать поля так же, как вы делаете в своем примере.
Ответ №2:
Создайте метод
public static void printFieldsFor(Class cls, Object obj) {
Field[] fields = cls.getDeclaredFields();
for ( Field field : fields ) {
String fieldName = field.getName();
String fieldValue = field.get(obj);
}
}
printFieldsFor(object.getClass(), obj);
printFieldsFor(object.getClass().getSuperclass(), obj);
или используйте цикл
for(Class cls = object.getClass();
cls!=null amp;amp; cls!=A.class;
cls = cls.getSuperclass()) {
for(Field field : cls.getDeclaredFields()) {
String fieldName = field.getName();
String fieldValue = field.get(obj);
// do something with the field.
}
}
Ответ №3:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author pablo.barbosa (2017-08-15)
*/
public class ReflectionUtil {
/**
* Hiding constructor. The methods are statics
*/
private ReflectionUtil() {
// Hiding constructor
}
public static List<Field> getInheritedDeclaredFields(Class<?> fromClass, Class<?> stopWhenClass) {
if (stopWhenClass == null) {
stopWhenClass = Object.class;
}
List<Field> fields = new ArrayList<>();
List<Class<?>> classes = new ArrayList<>();
Class<?> cls = fromClass;
do {
classes.add(cls);
cls = cls.getSuperclass();
} while (cls != null amp;amp; !cls.equals(stopWhenClass));
for (int i = classes.size() - 1; i >= 0; i--) {
fields.addAll(Arrays.asList(classes.get(i).getDeclaredFields()));
}
return fields;
}
public static Field getInheritedDeclaredField(Class<?> fromClass, String fieldName, Class<?> stopWhenClass) throws NoSuchFieldException {
if (stopWhenClass == null) {
stopWhenClass = Object.class;
}
Class<?> cls = fromClass;
do {
Field field;
try {
field = cls.getDeclaredField(fieldName);
if (field != null) {
return field;
}
} catch (NoSuchFieldException | SecurityException e) {
// Nothing. We'll try to get field from superclass
}
cls = cls.getSuperclass();
} while (cls != null amp;amp; !cls.equals(stopWhenClass));
// If we got here, we'll throw an exception
throw new NoSuchFieldException(fieldName);
}
public static Object getInheritedDeclaredFieldValue(Object obj, String fieldName, Class<?> stopWhenClass) throws NoSuchFieldException, IllegalAccessException {
Field field = getInheritedDeclaredField(obj.getClass(), fieldName, stopWhenClass);
field.setAccessible(true);
return field.get(obj);
}
}
Комментарии:
1. Обычно лучше не просто публиковать код с ответом. Но также объясните, почему.
Ответ №4:
вы можете просто получать поля из любого класса, используя этот код, независимо от его родительского или дочернего класса
for (Field field : YourClassName.class.getDeclaredFields()) {
//fields
}
Комментарии:
1. Неверно: из javadoc : возвращает массив объектов полей, отражающих все поля, объявленные классом или интерфейсом, представленным этим объектом класса. Это включает общедоступные, защищенные, доступ по умолчанию (пакет) и частные поля, но исключает унаследованные поля