我有这门课:
package scripts;
public class TestStatic {
public static void main(String[] args) {
new IncrA().incrStatic();
}
}
class Static {
public static int CPT = 0;
}
class IncrA{
public void incrStatic(){
for (int i:Range.ints(0,100)){
System.out.println("Now with "+this.toString()+" : Static.CPT="+Static.CPT);
Static.CPT++;
try{
Thread.sleep(100);
}
catch(Exception e){
e.printStackTrace();
}
}
System.out.println("Finally for execution of "+this.toString()+" : Static.CPT="+Static.CPT);
}
}
现在我从命令行在 Java 中运行类 TestStatic,两次。
javaw -cp ... scripts.TestStatic > 1.txt
javaw -cp ... scripts.TestStatic > 2.txt
我原以为第一次和第二次执行会干扰,并最终获得 Static.CPT == 200 的值,因为我认为 JVM 只会加载一次 Static 类。似乎并非如此。虽然我喜欢它,但我想知道我的这个例子是否足以得出 JVM 完全分离执行的结论。实际上,当我读取我的输出时,我的 IncrA 对象的 hashCode 在两次执行中通常是相同的:
来自 1.txt :
...
Now with scripts.IncrA@19f953d : Static.CPT=72
Now with scripts.IncrA@19f953d : Static.CPT=73
Now with scripts.IncrA@19f953d : Static.CPT=74
Now with scripts.IncrA@19f953d : Static.CPT=75
...
来自 2.txt :
...
Now with scripts.IncrA@19f953d : Static.CPT=72
Now with scripts.IncrA@19f953d : Static.CPT=73
Now with scripts.IncrA@19f953d : Static.CPT=74
Now with scripts.IncrA@19f953d : Static.CPT=75
...
@19f953d
在两个执行中共享。
我在 google 上搜索了有关 static 关键字的深入解释,但没有找到有关这些问题的任何信息。有人可以解释一下或给出一个很好的指示吗?
最佳答案
简短的回答:static
变量仅在单个 JVM 运行中持续存在,因此在您的第一次执行退出后,CPT
设置为 100 的事实实际上丢失了。参见 http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html有关静态变量与非静态变量的入门知识。简而言之,唯一的区别是静态变量由类的所有实例共享 - 否则,它们的行为基本上相同。
长(呃)的答案是,静态变量有点像实例变量,但对于您的类的 Class
对象。当 JVM 退出时,所有类都被卸载,因此静态变量不再存在,就像该类的任何实例不再存在一样。当您重新启动 Java 进行第二次运行时,它会从您的(编译的)源文件中重新读取您的类的定义,并按照您的要求将 CPT
设置为零。
(在您提到的情况下,同时运行两个 JVM 会导致两个 ClassLoaders
和两个不同的 Class
对象,每个 JVM 一个,因此它们每个都有自己的静态变量的版本。)
如果您想在 Java 执行之间保留任何信息,您需要将其存储在外部某处(例如文件或数据库),并在启动时加载此信息。如果要在运行的 Java 进程之间共享信息,则需要让它们相互通信以共享此信息(例如通过 TCP 连接)。无论所讨论的变量是否为静态,都是如此。
关于Java : static fields behaviour in different executions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1524456/