我已经在Stack Overflow和网络上的其他地方看到了有关静态变量的一些信息。但是答案对我来说还不清楚。当我认为找到答案时,其他一些说法与该声明相矛盾(或者至少我认为确实如此)。
例如:m0bius在How does the static keyword work in Java?中告诉我们(在“何时创建此副本[ed。静态变量]?”部分中),静态变量是在运行时创建的。但是,如果我检查https://en.wikipedia.org/wiki/Class_variable(“静态成员变量和静态成员函数”一节),则可以告诉我在某些语言中情况相反,而在其他语言中情况相同。
我的问题可以分为两个不同的问题:
我所说的编译时间与运行时间:
一些仅用于此问题的代码:
// MyClass.java
public class MyClass {
public static int instances;
public final static double PI = 3.14159265359
public MyClass() {
instances++;
}
// ...
}
// Main.java ; version 1
public class Main {
public static void main(String args[]) {
System.out.println("I am doing nothing with MyClass");
}
}
// OUTPUT: I am doing nothing with MyClass
// Main.java ; version 2
public class Main {
public static void main(String args[]) {
System.out.println("PI = " + MyClass.PI);
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
System.out.println("instances = " + MyClass.instances);
}
}
OUTPUT:
3.14159265359
2
如果在运行时同时创建 static 和 final static 变量,则在Main的第一个版本中,MyClass类的两个静态变量(实例和PI)都不会被创建。但是我会期望 final static 变量PI将在编译时创建(因此它将被“嵌入”在.class文件中),因为我认为这样做会有更好的性能(无论MyClass类发生什么情况,PI始终为3.14159265359,因此最好将其放在二进制文件中。
静态变量可能与此相同,但在整个程序中可能会发生变化。
答案 0 :(得分:4)
在Java中,是在运行时还是在编译时创建的类的静态变量?
在Java中,编译时不会“创建”变量,如果创建是指分配和初始化。它们都是在运行时创建的。它们是static
还是static final
与分配它们的 无关。
但是我会期望最终的静态变量PI将在编译时创建(因此它将被“嵌入”在.class文件中),因为我认为这样做会有更好的性能... >
这不是Java中的工作方式。当类文件被“编译”时,它们实际上基本上已经被编码了。当然,已经完成了一些工作,但是我们认为编译的很大一部分(就C语言而言)是在运行时发生的。当我们查看优化和内联时,尤其如此。
编译器会做一些准备工作,例如能够在可能的情况下提前计算字段(静态或实例)的值。例如,如果您按如下方式定义字段,则乘法将在编译时完成:
private long timeoutMillis = 10 * 24 * 3600 * 1000;
对于String
也是如此,在这种情况下,编译器将在可能的情况下将常量字符串附加在一起。以下代码在运行时不使用StringBuilder
,而是在编译时创建一个String
:
private static final String DEFAULT_HEADER = "A long headers that is " +
"broker into two lines\n";
但是,在两种情况下,字段(long timeoutMillis
和String DEFAULT_HEADER
)的分配和初始化都是在运行时完成的。
如果将在运行时同时创建静态变量和最终静态变量,则在Main的第一个版本中,不会创建类MyClass的两个静态变量(实例和PI)。
在您的示例中,在第一次加载时分配并初始化了static
字段(是否为final
)。因此,在您的第一个Main
中,instances
或PI
static
字段将不会像您提到的那样创建。在您的第二个示例中。一旦引用MyClass
,将加载类文件并创建static
字段。