使用Javareflection检索inheritance的属性名称/值
我有一个从“ParentObj”扩展的Java对象“ChildObj”。 现在,如果可以使用Javareflection机制检索ChildObj的所有属性名称和值,包括inheritance的属性,
Class.getFields给了我公共属性的数组,而Class.getDeclaredFields给了我所有字段的数组,但是他们都没有包含inheritance的字段列表。
有没有办法检索inheritance的属性?
不,你需要自己写。 这是一个在Class.getSuperClass()上调用的简单的recursion方法:
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; }
如果你想依靠一个库来实现这个function, 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()
根据需要recursioninheritance层次结构。
使用reflection库:
public Set<Field> getAllFields(Class<?> aClass) { return org.reflections.ReflectionUtils.getAllFields(aClass); }
recursion解决scheme是可以的,唯一的小问题是他们返回声明和inheritance成员的超集。 请注意,getDeclaredFields()方法也返回私有方法。 所以鉴于你浏览整个超类层次结构,你将包含在超类中声明的所有私有字段,而那些不能被inheritance。
一个简单的filter,带有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 …”解决scheme的工作版本
你可以试试:
Class parentClass = getClass().getSuperclass(); if (parentClass != null) { parentClass.getDeclaredFields(); }
更短,更less的对象实例化? ^^
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); } }