我有一个带有private static final字段的类,不幸的是,我需要在运行时更改.
使用反射我得到这个错误: java.lang.IllegalAccessException: Can not set static final boolean field
有没有办法改变价值?
Field hack = WarpTransform2D.class.getDeclaredField("USE_HACK");
hack.setAccessible(true);
hack.set(null, true);
Run Code Online (Sandbox Code Playgroud) Effective Java在单元测试单例上有以下声明
使类成为单例可能会使测试其客户端变得困难,因为除非它实现了作为其类型的接口,否则不可能将模拟实现替换为单例.
任何人都可以解释为什么会这样吗?
在Java中,事实证明,字段访问器被缓存,并且使用访问器具有副作用.例如:
class A {
private static final int FOO = 5;
}
Field f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
f.getInt(null); // succeeds
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // fails
Run Code Online (Sandbox Code Playgroud)
而
class A {
private static final int FOO = 5;
}
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // succeeds
Run Code Online (Sandbox Code Playgroud)
这是失败的堆栈跟踪的相关位:
java.lang.IllegalAccessException: Can not set static final int field A.FOO to (int)6 …Run Code Online (Sandbox Code Playgroud) java ×3
reflection ×2
final ×1
java-8 ×1
openjdk ×1
private ×1
singleton ×1
static ×1
unit-testing ×1