【发布时间】:2018-07-19 05:53:33
【问题描述】:
当我尝试更改嵌套静态类的静态最终成员的值时,我认为它不起作用。当我尝试使用以下代码更改其他类的静态最终成员时,它可以工作。
public class FinalPivateStaticMember {
public static void main(String[] args) {
System.out.println("Initial value == "+Test.val);
try {
Class cls = Class.forName("com.reflection.FinalPivateStaticMember$Test");
try {
Field file_systems_loaded = cls.getDeclaredField("val");
file_systems_loaded.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
try {
System.out.println("--"+file_systems_loaded.getModifiers());
modifiers.setInt(file_systems_loaded,file_systems_loaded.getModifiers() & ~Modifier.FINAL);
System.out.println("--"+file_systems_loaded.getModifiers());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
file_systems_loaded.setBoolean(null,false);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.print("Final value == "+Test.val);
}
static class Test{
private static final boolean val = true;
}
}
以上代码的输出
Initial value == true
--26
--10
Final value == true
【问题讨论】:
-
也许使用 getter 与直接访问字段有些不同...编译器以“内联”常量值而闻名,实际上,如果您在一个类中更改常量字段 (
public static final)并且不要重新编译使用该字段的其他类,它们仍将具有/使用旧值。 -
Java 语言规范中对此进行了解释:docs.oracle.com/javase/specs/jls/se9/html/…
-
附带说明,
Class.forName("com.reflection.FinalPivateStaticMember$Test")并没有比简单得多的Test.class带来任何好处。 -
@CarlosHeuberger 当然,使用 getter 不会改变任何东西,getter 方法中的访问会像任何其他访问一样内联。但除了
val是编译时常量这一事实之外,修改static final字段无论如何都超出规范,并且不能保证有效。
标签: java reflection