[英]<Java reflection> object.getClass().getDeclaredFields() is empty
[英]What is the difference between getFields and getDeclaredFields in Java reflection
我對使用 Java 反射時getFields
方法和getDeclaredFields
方法之間的區別有點困惑。
我讀到getDeclaredFields
可讓您訪問該類的所有字段,而getFields
僅返回公共字段。 如果是這種情況,為什么不總是使用getDeclaredFields
?
有人可以詳細說明這一點,並解釋這兩種方法之間的區別,以及何時/為什么要使用一種方法而不是另一種方法?
整個類層次結構中的所有public
字段。
所有字段,無論其可訪問性如何,但僅適用於當前類,而不適用於當前類可能繼承的任何基類。
為了讓所有字段都在層次結構中,我編寫了以下函數:
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
, Lists.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;
}
來自Java 反射教程:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.