有时我在程序中更改了静态字段,但是当程序运行时,它仍会获得旧数据。即使我重建工作区,它也行不通。
我使用Eclipse。编译器是否缓存常量值?我该如何避免这个问题?
Class Container {
public static String message = new String("original");
}
Class B {
public void printString() { System.out.println(Container.message); }
}
运行程序时,会打印出“原始”。后来我将Container.message更改为“已更改”,即使我已经构建了工作区,我的程序仍将打印出“原始”。这对我来说很奇怪。
答案 0 :(得分:3)
具有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
class
javac A.java B.java
rm A.class
java B
打印test
。
来自static
,final
字段的字符串已内联到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
)。