使用Java Reflection检索继承的属性名称/值
我是一个Java对象' ChildObj' 这是从'ParentObj'扩展而来的。 现在,如果可以使用Java反射机制检索ChildObj的所有属性名称和值,包括继承的属性?
Class.getFields为我提供了公共属性数组,Class.getDeclaredFields为我提供了所有字段的数组,但它们都没有包含继承的字段列表。
有没有办法检索继承的属性呢?
12个解决方案
155 votes
不,你需要自己写。 它是一个在Class.getSuperClass()上调用的简单递归方法:
public static List getAllFields(List 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(), LinkedList.class));
}
dfa answered 2019-07-08T21:36:36Z
77 votes
public static List getAllFields(Class> type) {
List fields = new ArrayList();
for (Class> c = type; c != null; c = c.getSuperclass()) {
fields.addAll(Arrays.asList(c.getDeclaredFields()));
}
return fields;
}
Esko Luontola answered 2019-07-08T21:36:52Z
32 votes
如果你想依靠一个库来完成这个,那么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 allFields = FieldUtils.getAllFieldsList(LinkedList.class);
// Get the fields form each individual class in the type's hierarchy
final List allFieldsClass = Arrays.asList(LinkedList.class.getFields());
final List allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields());
final List allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields());
final List 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));
}
}
Chris answered 2019-07-08T21:37:16Z
6 votes
你需要打电话:
Class.getSuperclass().getDeclaredFields()
根据需要递归继承层次结构。
Nick Holt answered 2019-07-08T21:37:46Z
5 votes
使用思考库:
public Set getAllFields(Class> aClass) {
return org.reflections.ReflectionUtils.getAllFields(aClass);
}
Lukasz Ochmanski answered 2019-07-08T21:38:10Z
3 votes
递归解决方案是可以的,唯一的小问题是它们返回已声明和继承成员的超集。 请注意,getDeclaredFields()方法也返回私有方法。 因此,只要您导航整个超类层次结构,您将包含在超类中声明的所有私有字段,并且那些不会被继承。
一个带Modifier.isPublic ||的简单过滤器 Modifier.isProtected谓词会做:
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isProtected;
(...)
List inheritableFields = new ArrayList();
for (Field field : type.getDeclaredFields()) {
if (isProtected(field.getModifiers()) || isPublic(field.getModifiers())) {
inheritableFields.add(field);
}
}
Marek Dec answered 2019-07-08T21:38:41Z
2 votes
private static void addDeclaredAndInheritedFields(Class> c, Collection fields) {
fields.addAll(Arrays.asList(c.getDeclaredFields()));
Class> superClass = c.getSuperclass();
if (superClass != null) {
addDeclaredAndInheritedFields(superClass, fields);
}
}
" DidYouMeanThatTomHa ..."的工作版本 解决方案如上
Theo Platt answered 2019-07-08T21:39:05Z
1 votes
你可以试试:
Class parentClass = getClass().getSuperclass();
if (parentClass != null) {
parentClass.getDeclaredFields();
}
Manuel Selva answered 2019-07-08T21:39:23Z
1 votes
更短,更少的对象实例化?^^
private static Field[] getAllFields(Class> type) {
if (type.getSuperclass() != null) {
return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields());
}
return type.getDeclaredFields();
}
Alexis LEGROS answered 2019-07-08T21:39:47Z
0 votes
private static void addDeclaredAndInheritedFields(Class c, Collection fields) {
fields.addAll(Arrays.asList(c.getDeclaredFields()));
Class superClass = c.getSuperclass();
if (superClass != null) {
addDeclaredAndInheritedFields(superClass, fields);
}
}
DidYouMeanThatTomHawtin answered 2019-07-08T21:40:04Z
0 votes
这是@ user1079877接受的答案的重写。 它可能是一个不修改函数参数的版本,也使用了一些现代Java特性。
public Field[] getFields(final Class 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);
scrutari answered 2019-07-08T21:40:34Z
0 votes
我最近在org.apache.commons.lang3.reflect.FieldUtils中看到了这段代码
public static List getAllFieldsList(final Class> cls) {
Validate.isTrue(cls != null, "The class must not be null");
final List allFields = new ArrayList<>();
Class> currentClass = cls;
while (currentClass != null) {
final Field[] declaredFields = currentClass.getDeclaredFields();
Collections.addAll(allFields, declaredFields);
currentClass = currentClass.getSuperclass();
}
return allFields;
}
aman answered 2019-07-08T21:40:58Z