簡體   English   中英

Java反射中getFields和getDeclaredFields有什么區別

[英]What is the difference between getFields and getDeclaredFields in Java reflection

我對使用 Java 反射時getFields方法和getDeclaredFields方法之間的區別有點困惑。

我讀到getDeclaredFields可讓您訪問該類的所有字段,而getFields僅返回公共字段。 如果是這種情況,為什么不總是使用getDeclaredFields

有人可以詳細說明這一點,並解釋這兩種方法之間的區別,以及何時/為什么要使用一種方法而不是另一種方法?

獲取字段()

整個類層次結構中的所有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檢索字段。 如果您確實需要Object字段,它可能為null

澄清Lists.newArrayListLists.newArrayList來自番石榴。

更新

僅供參考,上面的代碼發布在 GitHub 上我的LibEx項目中的ReflectionUtils

正如已經提到的, Class.getDeclaredField(String)只查看您調用它的Class中的字段。

如果要搜索Class層次結構中的Field ,可以使用這個簡單的函數:

/**
 * 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 對象表示的類或接口的所有可訪問公共字段 返回的數組中的元素沒有排序,也沒有任何特定的順序。 如果類或接口沒有可訪問的公共字段,或者它表示數組類、基本類型或 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM