Java获取和设置字段

示例

使用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继承的。