获取和设置字段
使用 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 继承而来的。