我尝试修改私有的最终静态变量,如下所示:
...try {
Field f =TargetA.class.getDeclaredField("RECV_TIMEOUT");
f.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(null, 12L);
} catch (Exception e) {
e.printStackTrace();//not reach here!
} ...
class TargetA{
private static final long RECV_TIMEOUT = 180000L;
}
Run Code Online (Sandbox Code Playgroud)
但TargetA.RECV_TIMEOUT仍然是180000L,没有任何异常.我在StackOverflow中搜索了问题,但找不到解决方案.
我猜Java版本1.6在反射中有更多的限制,这打破了OO规则.谢谢你的建议!
您可以通过这种方式更改静态最终字段,如果使用反射查看值,则会更改.您遇到的问题是编译器在编译时只进行一次内联常量优化.这意味着可以更改值,但不会更改使用常量的位置.
解决这个问题的方法是使用包装器方法来"混淆"编译器,这样就不必改变使用常量的方式.
public static final long RECV_TIMEOUT = runtime(180000L);
public static final <T> T runtime(T t) { return t; }
Run Code Online (Sandbox Code Playgroud)
final通过反射修改字段具有许多限制.特别是,如果final字段由编译时常量初始化,则可能无法观察到其新值(JLS 17.5.3最终字段的后续修改).
您可以使用以下解决方法:
class TargetA{
private static final long RECV_TIMEOUT = defaultTimeout();
private static long defaultTimeout() { return 180000L; }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
203 次 |
| 最近记录: |