有什麼辦法,使用反射來確定靜態final字段是否具有'='值(以便該值在訪問時將被內聯)或者其值是否由靜態初始化程序分配? 如果該字段確實有值,是否有任何方法來檢索該值而不使用Field.get方法(並因此導致靜態初始化程序被執行)?使用反射,我可以確定Java靜態最終字段是否內置?
3
A
回答
1
該字段只有在編譯時間常數時纔會「內聯」 - 請參閱JLS中冗長的定義。
所以它是不夠的,它是在宣佈時分配。 這不是一個編譯時間常數,雖然有效聲明:
static final int INT_CONST = compute();
static int compute() {
return 5;
}
只需通過反射,你無法確定該領域的初始化。
要訪問類字段的任何值,該類需要首先加載,因此無法阻止靜態初始化程序運行。
1
您不能反映這樣做,但你可以做到這一點使用字節碼工程庫像ASM:
public class AsmTest {
static final int a = 2; // constant
static final String b = "string"; // constant
static final String c = "foo "+"bar"; // constant: concatenation is allowed
static final String d = " foobar ".trim(); // not constant: method called
public static Object getFieldConstantValue(Class<?> clazz, final String field) {
try(InputStream is = clazz.getResourceAsStream(clazz.getSimpleName()+".class")) {
final Object[] value = {null};
new ClassReader(is).accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public FieldVisitor visitField(int access, String name, String desc,
String sig, Object val) {
if(name.equals(field))
value[0] = val;
return null;
}
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return value[0];
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
for(String name : new String[] {"a", "b", "c", "d"}) {
System.out.println(name+"="+getFieldConstantValue(AsmTest.class, name));
}
}
}
輸出:
a=2
b=string
c=foo bar
d=null
相關問題
- 1. 無法使用java反射更改靜態最終字段?
- 2. 使用「最終靜態」還是「靜態最終」是否正確?
- 3. 使用Java反射的Android更改私有靜態最終字段?
- 4. 是否可以使用最終的靜態類方法?
- 5. ==還是比較最終靜態字段
- 6. 從靜態類內使用反射獲取所有字段
- 7. 我可以在ejb 3.1單例中定義一個非最終靜態字段:
- 8. 強制Java編譯器不要內聯最終靜態字段
- 9. 是否可以使用反射來設置靜態類的靜態私有成員?
- 10. Kotlin中Java靜態最終字段的等價物是什麼?
- 11. 最終靜態字段的值可以在android中更改嗎?
- 12. 是否可以調試Java反射?
- 13. 機器人:改變私有靜態最終使用場Java反射
- 14. 確定反射類型是否可以投射到另一種反射類型
- 15. 使用Java反射,我可以訪問私有靜態嵌套類的私有字段嗎?
- 16. 設置靜態事件使用反射
- 17. 我是否正確使用靜態?
- 18. 確定是否可以爲給定值分配反射屬性
- 19. 確定一個字段是I型創建,使用反射
- 20. Java SE的靜態最終
- 21. 最終靜態可以更改嗎?
- 22. 使用反射獲取類型的靜態字段值
- 23. 使用反射,我可以列出#region中的字段?
- 24. 爲什麼我們可以有靜態最終成員,但不能在內部類中使用靜態方法?
- 25. 我可以使用Java反射獲取方法字段名稱嗎?
- 26. 初始化Java中的靜態最終字段
- 27. 通過反射獲取一個類的公共靜態最終字段/屬性的值在Java中
- 28. 是否可以在Java中擴展非靜態內部類?
- 29. 我是否以正確的方式使用靜態?
- 30. 我可以使用VS2010 PrivateObject訪問靜態類中的靜態字段嗎?
感謝這個,ASM聽起來像一個不錯的選擇。我假設ASM代碼不會導致執行靜態初始化程序? –
@RobertSales,不,它只是讀取它作爲'byte []'數組。這樣它可以讀取任何類,即使它沒有加載到應用程序中。 –