有几次我更改了程序中的静态字段,但当程序运行时,它仍然会获得旧的数据。即使我重建了工作区,它也不会工作。
我使用Eclipse。编译器是否缓存常量值?我如何避免这个问题?
Class Container {
public static String message = new String("original");
}
Class B {
public void printString() { System.out.println(Container.message); }
}当程序运行时,它会打印出“原始”。后来我把Container.message改成了"changed",即使我已经建立了工作区,我的程序仍然会打印出"original“。这对我来说很奇怪。
发布于 2013-07-04 15:25:12
内联
带有static final 和修饰符的字段由编译器内联。仅包含 static 修饰符的字段不会内联。
让我们有两个类
class A {
static final String X = "test";
}
class B {
public static void main (String... args) {
System.out.println(A.X);
}
}编译它们,删除A类,然后运行B类
javac A.java B.java
rm A.class
java B它打印test。
来自static的字符串,final字段内联到B类中。
如果我们从X字段中删除final修饰符,这个示例将失败。
class A {
static String X = "test";
}
class B {
public static void main (String... args) {
System.out.println(A.X);
}
}编译它们,删除A类,然后运行B类
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字段的代码是不可见的。
编译器问题
要知道,Eclipse使用它自己的编译器,它的行为方式与JDK编译器不同。
如果你有一个有问题的类。反编译它
javap -c B.class并检查它是否访问了您想要的字段
3: getstatic #3 // Field A.X:Ljava/lang/String;或者是内联的
3: ldc #3 // String test发布于 2013-07-04 15:16:22
看起来你对静态字段有完全错误的理解。静态字段是类变量,即所有对象将共享应用程序的一个副本。但是JVM不会为程序的不同运行保留静态字段。因此,期望如果您在一次运行中设置某个静态字段的值,那么您将获得该字段的相同值,这是一个完全错误的概念。
如果你想保留这些值,那么可以使用序列化,但即使这样也是为了存储对象的状态,而不是真正用于静态字段。
发布于 2013-07-04 15:45:28
你能试试下面的代码吗?它对我来说是完美的。
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); }
}https://stackoverflow.com/questions/17463973
复制相似问题