静态字段不会更新

时间:2013-07-04 07:12:15

标签: java eclipse static

有时我在程序中更改了静态字段,但是当程序运行时,它仍会获得旧数据。即使我重建工作区,它也行不通。
我使用Eclipse。编译器是否缓存常量值?我该如何避免这个问题?

Class Container {
    public static String message = new String("original");
}

Class B {
    public void printString() { System.out.println(Container.message); }
}

运行程序时,会打印出“原始”。后来我将Container.message更改为“已更改”,即使我已经构建了工作区,我的程序仍将打印出“原始”。这对我来说很奇怪。

4 个答案:

答案 0 :(得分:3)

内联

具有staticfinal修饰符的字段由编译器内联。仅包含static修饰符的字段不会内联。

我们有两个班级

class A {
    static final String X = "test";
}

class B {
    public static void main (String... args) {
        System.out.println(A.X);
    }
}

编译它们,删除A类,然后运行B class

javac A.java B.java
rm A.class
java B

打印test

来自staticfinal字段的字符串已内联到B类。


如果我们从final字段中删除X修饰符,则此示例将失败。

class A {
    static String X = "test";
}

class B {
    public static void main (String... args) {
        System.out.println(A.X);
    }
}

编译它们,删除A类,然后运行B class

javac A.java B.java
rm A.class
java B

我们得到了

Exception in thread "main" java.lang.NoClassDefFoundError: A
    at B.main(B.java:3)
Caused by: java.lang.ClassNotFoundException: A
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

为了避免陈旧内联值问题,请立即重新编译所有来源。

类加载器

如果A类加载了两个不同的类加载器,则可能会出现另一个问题。这将导致A类的两个副本。一个static字段中的static字段值的更改对于引用另一个字段的javap -c B.class 字段的代码将不可见。

编译器问题

请注意Eclipse使用自己的Java编译器,其行为与JDK编译器不同。

如果你有一个有问题的课程。反编译

3: getstatic     #3                  // Field A.X:Ljava/lang/String;

并检查它是否访问了您想要的字段

3: ldc           #3                  // String test

或是内联

{{1}}

答案 1 :(得分:2)

您似乎对静态字段有完全错误的看法。静态字段是类变量,即所有对象将共享应用程序的一个副本。但是,对于程序的不同运行,JVM不会保留静态字段。因此,如果你在一次运行中设置静态字段的某个值,那么你将得到相同的字段值是一个完全错误的概念。

如果你想保留这些值,那么就去串行,但即便是存储对象的状态,而不是真正意义上的静态字段。

答案 2 :(得分:0)

你能试试下面的代码吗?它非常适合我。

class  MainClass {

    public static void main(String a[]){
        //before changing the value
        System.out.println(" before changing the value ");
        B b = new B();
        b.printString();

        //changing the value
        Container.message = "changed";
        System.out.println(" after changing the value ");
        b.printString();
    }
}


class Container {
    public static String message = new String("original");
}

class B {
    public void printString() { System.out.println(Container.message); }
}

答案 3 :(得分:0)

有时在Eclipse中会发生这种情况,特别是在旧版本中(我没有遇到Eclipse 4.x的这个问题)。尝试清理生成的.class并再次构建它们(Project -> Clean...)。还要确保选中Project -> Build Automatically,这样每次更改时都会自动调用编译器。如果这不起作用,请尝试重新启动Eclipse(File -> Restart)。