2010-01-07 80 views
0

我有一個抽象類,如下所示。我想獲得所有成員變量的值。使用反射在Java中獲取成員變量值的陷阱

public abstract class PARAMS { 
    public static final String NAME1 = "VAL1"; 
    public static final String NAME2 = "VAL2"; 
    public static final String NAME3 = "VAL3"; 
} 

使用反射檢索值如下。

Field[] fields = PARAMS.class.getFields(); 
for (Field field : fields) { 
    String name = field.getName() ; 
    String value = (String) field.get(name); 
} 

這是我第一次嘗試反思。這是實現目標的正確方法嗎?我想知道在這種情況下使用反射有什麼缺陷。

回答

4

您的代碼在迭代靜態和私人領域。所以你應該檢查你是否只在靜態字段上進行迭代。

for (Field field : PARAMS.class.getFields()) { 
    if (Modifiered.isStatic(field.getModifiers())) continue; 
    String name = field.getName() ; 
    String value = (String) field.get(PARAMS.class); 
} 

NB:作爲喬恩提到的,對於靜態字段訪問實例參數被忽略。但是,我更喜歡通過類而不是null,因爲這是縮進的更好的文檔。

然而,更好的做法是使用註釋來標註字段,以便只有那些你真正想要的字段不會被其他程序員(或者甚至是幕後的Java語言)添加其他靜態字段。如果你這樣做,你的代碼看起來像

for (Field field : PARAMS.class.getFields()) { 
    if (!field.isAnnotationsPresent(YourAnnotation.class)) continue; 
    String name = field.getName() ; 
    String value = (String) field.get(PARAMS.class); 
} 
3

這是不完全正確 - 將參數get理論上應爲null可讀性的原因:這樣的說法的一點是給它一個目標,當你檢索實例字段。

所以,你的代碼可以只是:

Field[] fields = PARAMS.class.getFields(); 
for (Field field : fields) { 
    String name = field.getName() ; 
    String value = (String) field.get(null); 
} 

現在,這應該工作...但你會怎樣使用這些值呢?你有什麼理由要這樣做,而不是創建一個直接暴露的不可變的Map<String, String>

反射是很好的地方,它是必要的,但你還沒有提供足夠的信息來確定它是否真的有必要在這個的情況下。

0

另一個問題,getFields返回所有可用的字段這個類的(靜態的或無意的)和它的所有超。對於您發佈的特定代碼而言不是問題,因爲唯一的超類是Object,它沒有公共字段。
我至少會測試該字段是否在正確的類中聲明 - getDeclaringClass() - 以及它是否具有正確的返回類型 - getType()

正如Adrian所建議的,使用Annotation是最好的恕我直言。