使用Java Reflection检索继承的属性名称/值

Vee*_*era 118 java reflection introspection

我有一个Java对象'ChildObj',它从'ParentObj'扩展而来.现在,如果可以使用Java反射机制检索ChildObj的所有属性名称和值,包括继承的属性?

Class.getFields为我提供了公共属性数组,Class.getDeclaredFields为我提供了所有字段的数组,但它们都没有包含继承的字段列表.

有没有办法检索继承的属性呢?

dfa*_*dfa 163

不,你需要自己写.它是一个在Class.getSuperClass()上调用的简单递归方法:

public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
    fields.addAll(Arrays.asList(type.getDeclaredFields()));

    if (type.getSuperclass() != null) {
        getAllFields(fields, type.getSuperclass());
    }

    return fields;
}

@Test
public void getLinkedListFields() {
    System.out.println(getAllFields(new LinkedList<Field>(), LinkedList.class));
}
Run Code Online (Sandbox Code Playgroud)

  • 传递一个可变参数并返回它可能不是一个很好的设计.fields.addAll(type.getDeclaredFields()); 比使用add的增强for循环更常规. (7认同)
  • 是.想到这一点.但想检查是否有其他方法可以做到这一点.谢谢.:) (2认同)

Esk*_*ola 83

    public static List<Field> getAllFields(Class<?> type) {
        List<Field> fields = new ArrayList<Field>();
        for (Class<?> c = type; c != null; c = c.getSuperclass()) {
            fields.addAll(Arrays.asList(c.getDeclaredFields()));
        }
        return fields;
    }
Run Code Online (Sandbox Code Playgroud)

  • 这是我的首选解决方案,但我称之为"getAllFields",因为它也会返回给定类的字段. (9认同)
  • 虽然我非常喜欢递归(它很有趣!),我更喜欢这种方法的可读性和更直观的参数(不需要传递新的集合),不再需要(隐含在for子句中)而不是迭代字段他们自己. (3认同)

Chr*_*ris 34

如果您想依靠库来实现这一目标,那么Apache Commons Lang版本3.2+提供FieldUtils.getAllFieldsList:

import java.lang.reflect.Field;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.AbstractSequentialList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.junit.Assert;
import org.junit.Test;

public class FieldUtilsTest {

    @Test
    public void testGetAllFieldsList() {

        // Get all fields in this class and all of its parents
        final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class);

        // Get the fields form each individual class in the type's hierarchy
        final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields());
        final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields());
        final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields());
        final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields());

        // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
        Assert.assertTrue(allFields.containsAll(allFieldsClass));
        Assert.assertTrue(allFields.containsAll(allFieldsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 繁荣!我不喜欢重新发明轮子.为此欢呼. (6认同)

Ama*_*man 7

getFields(): 获取整个类层次结构中的所有公共字段,而
getDeclaredFields(): 获取所有字段,无论其修饰符如何,但仅适用于当前类。因此,您必须了解所有涉及的层次结构。
我最近从org.apache.commons.lang3.reflect.FieldUtils看到了这段代码

public static List<Field> getAllFieldsList(final Class<?> cls) {
        Validate.isTrue(cls != null, "The class must not be null");
        final List<Field> allFields = new ArrayList<>();
        Class<?> currentClass = cls;
        while (currentClass != null) {
            final Field[] declaredFields = currentClass.getDeclaredFields();
            Collections.addAll(allFields, declaredFields);
            currentClass = currentClass.getSuperclass();
        }
        return allFields;
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*olt 6

你需要打电话:

Class.getSuperclass().getDeclaredFields()
Run Code Online (Sandbox Code Playgroud)

根据需要递归继承层次结构.


Luk*_*ski 5

使用思考库:

public Set<Field> getAllFields(Class<?> aClass) {
    return org.reflections.ReflectionUtils.getAllFields(aClass);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ças 5

使用 spring util 库,您可以用来检查类中是否存在一个特定属性:

Field field = ReflectionUtils.findRequiredField(YOUR_CLASS.class, "ATTRIBUTE_NAME");

log.info(field2.getName());
Run Code Online (Sandbox Code Playgroud)

API文档:
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/util/ReflectionUtils.html

或者

 Field field2 = ReflectionUtils.findField(YOUR_CLASS.class, "ATTRIBUTE_NAME");

 log.info(field2.getName());
Run Code Online (Sandbox Code Playgroud)

API文档:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/ReflectionUtils.html

@干杯