‘ParentObj’에서 확장 된 Java 객체 ‘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 술어는 다음을 수행합니다.
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 …”솔루션의 작업 버전