문제

나는 'Parentobj'에서 확장 된 Java Object 'Childobj'입니다. 이제 Java 반사 메커니즘을 사용하여 상속 된 속성을 포함하여 Childobj의 모든 속성 이름과 값을 검색 할 수 있다면?

class.getFields 공개 속성의 배열을 제공합니다 class.getDeclaredFields 모든 필드의 배열을 제공하지만 상속 필드 목록이 포함되어 있지 않습니다.

상속 된 속성도 검색 할 수있는 방법이 있습니까?

도움이 되었습니까?

해결책

아니요, 직접 써야합니다. 그것은 단순한 재귀 방법입니다 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));
}

다른 팁

    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;
    }

대신이를 달성하기 위해 도서관에 의존하고 싶다면 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));
    }
}

전화해야합니다.

Class.getSuperclass().getDeclaredFields()

필요에 따라 상속 계층 구조를 되풀이합니다.

반사 라이브러리 사용 :

public Set<Field> getAllFields(Class<?> aClass) {
    return org.reflections.ReflectionUtils.getAllFields(aClass);
}

재귀 솔루션은 괜찮습니다. 유일한 작은 문제는 선언되고 상속 된 회원의 슈퍼 세트를 반환한다는 것입니다. getDeclaredFields () 메소드는 개인 메소드도 반환합니다. 따라서 전체 슈퍼 클래스 계층 구조를 탐색하면 슈퍼 클래스에 선언 된 모든 개인 필드를 포함 시키며 상속되지 않습니다.

modifier.ispublic ||가있는 간단한 필터 Modifier.isprotected Precticate는 다음과 같습니다.

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);
    }
}
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 ..."솔루션의 작업 버전

당신은 시도 할 수 있습니다:

   Class parentClass = getClass().getSuperclass();
   if (parentClass != null) {
      parentClass.getDeclaredFields();
   }

더 짧고 적은 물체가 인스턴스화되어 있습니까? ^^

private static Field[] getAllFields(Class<?> type) {
    if (type.getSuperclass() != null) {
        return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields());
    }
    return type.getDeclaredFields();
}
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);
    }
}

이것은 @user1079877에 의해 허용 된 답변을 다시 작성한 것입니다. 함수의 매개 변수를 수정하지 않고 일부 최신 Java 기능을 사용하는 버전 일 수도 있습니다.

public <T> Field[] getFields(final Class<T> type, final Field... fields) {
    final Field[] items = Stream.of(type.getDeclaredFields(), fields).flatMap(Stream::of).toArray(Field[]::new);
    if (type.getSuperclass() == null) {
        return items;
    } else {
        return getFields(type.getSuperclass(), items);
    }
}

이 구현은 또한 호출을 조금 더 간결하게 만듭니다.

var fields = getFields(MyType.class);

최근 에이 코드를 보았습니다 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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top