学习Java时,您被告知可以使用最后关键字,并且它们拥有的值(或对象引用)永远不能更改,否则,它们将不被称为常量,对吗?
几乎是真的。 实际上,您可以使用称为反射的技术来更改常数的值。 使用反射,您可以在运行时以编程方式访问和更改有关字段,方法和已加载类的构造函数的信息。
在此示例中,我们将私有常数AGE从50更改为15:
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ModifyConstant {
public static void main(String[] args) throws Exception {
OldPerson fakeYoungPerson = new OldPerson();
changePrivateConstant(fakeYoungPerson, "AGE", 15);
fakeYoungPerson.sayYourAge();
}
public static void changePrivateConstant(Object instance, String constantName, Object newValue) throws Exception {
// gets the Field object which represents the constant
Field field = instance.getClass().getDeclaredField(constantName);
// need this because AGE is 'private'
field.setAccessible(true);
Field modifiers = field.getClass().getDeclaredField("modifiers");
// need this because modifiers of any Field are 'private'
modifiers.setAccessible(true);
// this kind of removes the 'final' keyword.
// it actually turns off the bit representing the 'final' modifier
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
// and now we are able to set the new value to the constant
field.set(instance, newValue);
}
}
class OldPerson {
private static final Integer AGE = 50;
public void sayYourAge() {
System.out.println("I'm " + AGE + " yo only!");
}
}
编译并运行此类后的结果输出为:
I'm 15 yo only!
当然,更改常数是一个完全奇怪的用例,尽管我认为这可能引起了您的注意(对吗?)。 尽管如此,反射是一项强大的技术,可帮助开发人员创建可动态配置的组件。 您还需要注意,反射会在性能方面付出很多代价,因此请明智地使用反射,并且仅在真正需要时使用。
我要说的最后一件事是,如果常量是类型,则此特定示例将不起作用串因为Java 串 Constant Pool,但这是一个不同的故事,我将在后面讲...