151

「ParentObj」から拡張されたJavaオブジェクト「ChildObj」があります。さて、Javaリフレクションメカニズムを使用して、継承された属性も含めて、ChildObjのすべての属性名と値を取得できる場合はどうでしょうか。

Class.getFieldsはパブリック属性の配列を提供し、Class.getDeclaredFieldsはすべてのフィールドの配列を提供しますが、継承されたフィールドのリストは含まれていません。

継承された属性も取得する方法はありますか?

4

14 に答える 14

98
    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;
    }
于 2010-03-09T00:15:57.250 に答える
39

代わりに、これを達成するためにライブラリに依存したい場合は、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));
    }
}
于 2014-05-28T15:27:20.977 に答える
5

反射ライブラリを使用:

public Set<Field> getAllFields(Class<?> aClass) {
    return org.reflections.ReflectionUtils.getAllFields(aClass);
}
于 2016-06-10T10:23:19.120 に答える
4

再帰的な解決策は問題ありません。唯一の小さな問題は、宣言および継承されたメンバーのスーパーセットを返すことです。getDeclaredFields() メソッドはプライベート メソッドも返すことに注意してください。したがって、スーパークラス階層全体をナビゲートすると、スーパークラスで宣言されたすべてのプライベート フィールドが含まれ、それらは継承されません。

Modifier.isPublic || を使用した単純なフィルター Modifier.isProtected 述語は次のようになります。

import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isProtected;

(...)

List<Field> inheritableFields = new ArrayList<Field>();
for (Field field : type.getDeclaredFields()) {
    if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) {
       inheritableFields.add(field);
    }
}
于 2011-12-22T00:16:09.363 に答える
2
private static void addDeclaredAndInheritedFields(Class<?> c, Collection<Field> fields) {
    fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    Class<?> superClass = c.getSuperclass(); 
    if (superClass != null) { 
        addDeclaredAndInheritedFields(superClass, fields); 
    }       
}

上記の「DidYouMeanThatTomHa ...」ソリューションの作業バージョン

于 2011-02-17T21:51:00.927 に答える
0
private static void addDeclaredAndInheritedFields(Class c, Collection<Field> fields) {
    fields.addAll(Arrays.asList(c.getDeclaredFields()));
    Class superClass = c.getSuperclass();
    if (superClass != null) {
        addDeclaredAndInheritedFields(superClass, fields);
    }
}
于 2010-03-09T00:06:40.997 に答える