使用Reflection API,可以在运行时更改或获取字段的值。例如,您可以在API中使用它,以根据某个因素(例如操作系统)来检索不同的字段。您也可以删除修饰符,例如final允许修饰最终的字段。
为此,您将需要以getField()如下所示的方式使用Class#方法:
// 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
// 需要是静态的
Field modifiersField = Field.class.getDeclaredField("modifiers");
// 即使宣布为私有也允许任何人访问
modifiersField.setAccessible(true);
// Get the modifiers on the "NAME" field as an int.
int existingModifiersOnNameField = nameField.getModifiers();
// 现有修饰符上的按位AND NOTModifier.FINAL(16)
// Readup here https://en.wikipedia.org/wiki/Bitwise_operations_in_C
// 如果不确定什么是按位运算。
int newModifiersOnNameField = existingModifiersOnNameField & ~Modifier.FINAL;
// 为非静态字段设置对象下的修饰符字段的值
modifiersField.setInt(nameField, newModifiersOnNameField);
//将其设置为可访问。这将覆盖普通的Java
// 私有/受保护/程序包/等访问控制检查。
nameField.setAccessible(true);
// Set the value of "NAME" here. Note the null argument.
// 修改静态字段时传递null,因为没有实例对象
nameField.set(null, "被反射砍死...");
//在这里我可以直接访问它。如果需要,请使用反射进行获取。(下面)
System.out.println(SomeClass.NAME);获取字段要容易得多。我们可以使用Field#get()及其变体来获取其值:
// Get the field in class SomeClass "NAME".
Field nameField = SomeClass.class.getDeclaredField("NAME");
// 设置为私有字段可访问
nameField.setAccessible(true);
// 传递null因为没有实例,还记得吗?
String name = (String) nameField.get(null);请注意以下几点:
使用Class#getDeclaredField时,可使用它来获取类本身中的字段:
class HackMe extends Hacked {
public String iAmDeclared;
}
class Hacked {
public String someState;
}在这里,HackMe#iAmDeclared是声明字段。但是,HackMe#someState不是声明的字段,因为它是从其超类Hacked继承的。