首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态字段不更新

静态字段不更新
EN

Stack Overflow用户
提问于 2013-07-04 15:12:15
回答 4查看 1.6K关注 0票数 2

有几次我更改了程序中的静态字段,但当程序运行时,它仍然会获得旧的数据。即使我重建了工作区,它也不会工作。

我使用Eclipse。编译器是否缓存常量值?我如何避免这个问题?

代码语言:javascript
复制
Class Container {
    public static String message = new String("original");
}

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

当程序运行时,它会打印出“原始”。后来我把Container.message改成了"changed",即使我已经建立了工作区,我的程序仍然会打印出"original“。这对我来说很奇怪。

EN

回答 4

Stack Overflow用户

发布于 2013-07-04 15:25:12

内联

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

让我们有两个类

代码语言:javascript
复制
class A {
    static final String X = "test";
}

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

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

代码语言:javascript
复制
javac A.java B.java
rm A.class
java B

它打印test

来自static的字符串,final字段内联到B类中。

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

代码语言:javascript
复制
class A {
    static String X = "test";
}

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

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

代码语言:javascript
复制
javac A.java B.java
rm A.class
java B

我们就会得到

代码语言:javascript
复制
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字段的代码是不可见的。

编译器问题

要知道,Eclipse使用它自己的编译器,它的行为方式与JDK编译器不同。

如果你有一个有问题的类。反编译它

代码语言:javascript
复制
javap -c B.class

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

代码语言:javascript
复制
3: getstatic     #3                  // Field A.X:Ljava/lang/String;

或者是内联的

代码语言:javascript
复制
3: ldc           #3                  // String test
票数 3
EN

Stack Overflow用户

发布于 2013-07-04 15:16:22

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

如果你想保留这些值,那么可以使用序列化,但即使这样也是为了存储对象的状态,而不是真正用于静态字段。

票数 2
EN

Stack Overflow用户

发布于 2013-07-04 15:45:28

你能试试下面的代码吗?它对我来说是完美的。

代码语言:javascript
复制
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); }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17463973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档