我有一个Java对象'ChildObj',它是从'ParentObj'扩展而来的。现在,是否可以使用Java反射机制检索ChildObj的所有属性名称和值,包括继承属性?
Class.getFields 给我公共属性数组,Class.getDeclaredFields 给我所有字段数组,但它们都不包括继承字段列表。
有没有办法检索继承的属性呢?
我有一个Java对象'ChildObj',它是从'ParentObj'扩展而来的。现在,是否可以使用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()
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;
}
使用Reflections库:
public Set<Field> getAllFields(Class<?> aClass) {
return org.reflections.ReflectionUtils.getAllFields(aClass);
}
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);
}
}
使用Spring工具库,您可以检查一个特定属性是否存在于类中:
Field field = ReflectionUtils.findRequiredField(YOUR_CLASS.class, "ATTRIBUTE_NAME");
log.info(field2.getName());
或者
Field field2 = ReflectionUtils.findField(YOUR_CLASS.class, "ATTRIBUTE_NAME");
log.info(field2.getName());
@cheers
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..." 解决方案的工作版本
private static Field[] getAllFields(Class<?> type) {
if (type.getSuperclass() != null) {
return (Field[]) ArrayUtils.addAll(getAllFields(type.getSuperclass()), type.getDeclaredFields());
}
return type.getDeclaredFields();
}