Java反射中的getFields和getDeclaredFields有什么区别

时间:2013-06-06 15:51:09

标签: java reflection

使用Java反射时,我对getFields方法和getDeclaredFields方法之间的区别感到有些困惑。

我读到getDeclaredFields可让您访问该类的所有字段,而getFields仅返回公共字段。如果是这种情况,为什么不总是使用getDeclaredFields

有人可以详细说明这一点,并解释两种方法之间的区别,以及何时/为什么要使用另一种方法?

4 个答案:

答案 0 :(得分:221)

<强> getFields()

整个类层次结构中的所有public个字段。

<强> getDeclaredFields()

所有字段,无论其可访问性如何,但仅适用于当前类,而不是当前类可能继承的任何基类。

为了获得层次结构中的所有字段,我编写了以下函数:

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中检索字段。如果您想要null字段,可能是Object

澄清一下,Lists.newArrayList来自番石榴。

更新

仅供参考,以上代码在LibExReflectionUtils项目中的GitHub上发布。

答案 1 :(得分:6)

如前所述,SELECT 0x1c | 0xf 仅查看您调用它的Class.getDeclaredField(String)字段。

如果要搜索Class层次结构中的Field,可以使用此简单功能:

Class

例如,这对于从超类中查找/** * 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

答案 2 :(得分:4)

public Field[] getFields() throws SecurityException

返回一个数组,其中包含反映此Class对象所代表的类或接口的所有 可访问公共字段 的Field对象。返回的数组中的元素没有排序,也没有任何特定的顺序。如果类或接口没有可访问的公共字段,或者它表示数组类,基本类型或void,则此方法返回长度为0的数组。

具体来说,如果此Class对象表示一个类,则此方法返回 此类及其所有超类的公共字段。 如果此Class对象表示接口,此方法返回此接口及其所有超接口的字段。

此方法不反映数组类的隐式长度字段。用户代码应该使用类Array的方法来操作数组。


public Field[] getDeclaredFields() throws SecurityException

返回一个Field对象数组,反映所有 由类 声明的字段或此Class对象表示的接口。此 包括公开,受保护,默认(包)访问和私有 字段,但 排除了继承的 字段。返回的数组中的元素没有排序,也没有任何特定的顺序。如果类或接口声明没有字段,或者此Class对象表示基本类型,数组类或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;
}

答案 3 :(得分:0)

相关问题