獲取和設定欄位
使用 Reflection API,可以在執行時更改或獲取欄位的值。例如,你可以在 API 中使用它來根據作業系統等因素檢索不同的欄位。你還可以刪除像 final
這樣的修飾符,以允許修改最終的欄位。
為此,你需要使用方法 Class#getField()
,方法如下所示:
// Get the field in class SomeClass "NAME".
Field nameField = SomeClass.class.getDeclaredField("NAME");
// Get the field in class Field "modifiers". Note that it does not
// need to be static
Field modifiersField = Field.class.getDeclaredField("modifiers");
// Allow access from anyone even if it's declared private
modifiersField.setAccessible(true);
// Get the modifiers on the "NAME" field as an int.
int existingModifiersOnNameField = nameField.getModifiers();
// Bitwise AND NOT Modifier.FINAL (16) on the existing modifiers
// Readup here https://en.wikipedia.org/wiki/Bitwise_operations_in_C
// if you're unsure what bitwise operations are.
int newModifiersOnNameField = existingModifiersOnNameField & ~Modifier.FINAL;
// Set the value of the modifiers field under an object for non-static fields
modifiersField.setInt(nameField, newModifiersOnNameField);
// Set it to be accessible. This overrides normal Java
// private/protected/package/etc access control checks.
nameField.setAccessible(true);
// Set the value of "NAME" here. Note the null argument.
// Pass null when modifying static fields, as there is no instance object
nameField.set(null, "Hacked by reflection...");
// Here I can directly access it. If needed, use reflection to get it. (Below)
System.out.println(SomeClass.NAME);
獲得田地更容易。我們可以使用 Field#get()
及其變體來獲取它的值:
// Get the field in class SomeClass "NAME".
Field nameField = SomeClass.class.getDeclaredField("NAME");
// Set accessible for private fields
nameField.setAccessible(true);
// Pass null as there is no instance, remember?
String name = (String) nameField.get(null);
請注意這個:
使用 Class#getDeclaredField 時 ,使用它來獲取類本身中的欄位:
class HackMe extends Hacked {
public String iAmDeclared;
}
class Hacked {
public String someState;
}
在這裡,HackMe#iAmDeclared
被宣告為 field。但是,HackMe#someState
不是宣告的欄位,因為它是從它的超類 Hacked 繼承而來的。