【问题标题】:Changing the value of final static member of a nested static class [duplicate]更改嵌套静态类的最终静态成员的值[重复]
【发布时间】: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


【解决方案1】:

该值实际上是在变化的,但由于编译器优化,您在打印语句中看不到变化。 编译器可以(并且将)用它们所持有的值替换原始(和String)静态最终字段的出现。所以编译后你的打印语句将相当于

System.out.print("Final value == "+true)

请注意,在编译阶段,变量会被替换为它的源值。

【讨论】:

  • 关于编译时常量的行为不仅仅是一种优化,它是一种强制行为。由于字符串与编译时常量的连接也会产生编译时常量,因此实际编译的代码等价于System.out.print("Final value == true");...
猜你喜欢
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多