Javareflection中的getFields和getDeclaredFields有什么不同?
在使用Javareflection时,我对getFields
方法和getDeclaredFields
方法之间的区别有些困惑。
我读了getDeclaredFields
让你访问类的所有字段,而getFields
只返回公共字段。 如果是这种情况,为什么不总是使用getDeclaredFields
?
有人可以详细说明这一点,并解释两种方法之间的区别,什么时候/为什么你会想要使用一个在另一个?
getFields()
所有的public
字段都在整个类层次结构中。
getDeclaredFields()
所有的字段,不pipe它们的可访问性, 只针对当前类,而不是当前类可能inheritance的任何基类。
将所有的字段放在层次结构中
我写了下面的函数:
public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass, @Nullable Class<?> exclusiveParent) { List<Field> currentClassFields = Lists.newArrayList(startClass.getDeclaredFields()); Class<?> parentClass = startClass.getSuperclass(); if (parentClass != null && (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) { List<Field> parentClassFields = (List<Field>) getFieldsUpTo(parentClass, exclusiveParent); currentClassFields.addAll(parentClassFields); } return currentClassFields; }
提供了exclusiveParent
类来防止从Object
检索字段。 如果你想要Object
字段,则可能为null
。
为了说明, Lists.newArrayList
来自Guava。
更新
仅供参考,上面的代码在ReflectionUtils的 LibEx项目的GitHub上发布。
正如已经提到的, Class.getDeclaredField(String)
只会查看您调用它的Class
中的字段。
如果要在Class
层次结构中searchField
,则可以使用以下简单函数:
/** * Returns the first {@link Field} in the hierarchy for the specified name */ public static Field getField(Class<?> clazz, String name) { Field field = null; while (clazz != null && field == null) { try { field = clazz.getDeclaredField(name); } catch (Exception e) { } clazz = clazz.getSuperclass(); } return field; }
例如,从超类中查找private
字段非常有用。 另外,如果你想修改它的值,你可以像这样使用它:
/** * Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name */ public static void setField(Object object, String fieldName, Object value) throws Exception { Field field = getField(object.getClass(), fieldName); field.setAccessible(true); field.set(object, value); }
public Field[] getFields() throws SecurityException
返回一个包含Field对象的数组,该对象反映了由此Class对象表示的类或接口的所有可访问的公共字段 。 返回的数组中的元素没有sorting,也没有任何特定的顺序。 如果类或接口没有可访问的公共字段,或者表示数组类,基元types或void,则此方法返回长度为0的数组。
具体而言,如果此Class对象表示一个类,则此方法将返回此类及其所有超类的公共字段。 如果此Class对象表示一个接口,则此方法将返回此接口及其所有超接口的字段。
数组类的隐含长度字段不反映这种方法。 用户代码应该使用类Array的方法来操作数组。
public Field[] getDeclaredFields() throws SecurityException
返回一个Field对象的数组,该对象反映由此Class对象表示的类或接口声明的所有字段 。 这包括公共,受保护,默认(包)访问和专用字段,但不包括inheritance的字段。 返回的数组中的元素没有sorting,也没有任何特定的顺序。 如果类或接口声明不存在字段,或者此Class对象表示原始types,数组类或void,则此方法返回长度为0的数组。
如果我需要所有父类的所有字段呢? 一些代码是必需的,例如从https://stackoverflow.com/a/35103361/755804 :
public static List<Field> getAllModelFields(Class aClass) { List<Field> fields = new ArrayList<>(); do { Collections.addAll(fields, aClass.getDeclaredFields()); aClass = aClass.getSuperclass(); } while (aClass != null); return fields; }