gpt4 book ai didi

java - Java 中如何处理 static final 和 static 成员?

转载 作者:行者123 更新时间:2023-11-29 08:24:15 28 4
gpt4 key购买 nike

我已经在 Stack Overflow 和网络上的其他地方看到了一些关于静态变量的信息。但是我不清楚答案。当我认为我找到了答案时,其他一些来源与该陈述相矛盾(或者至少,我认为是这样)。

例如:m0bius 告诉我们 How does the static keyword work in Java? (在“此副本何时创建[编辑静态变量]?”部分中)静态变量是在运行时创建的。但是如果我检查 https://en.wikipedia.org/wiki/Class_variable (“静态成员变量和静态成员函数”部分)它告诉我在某些语言中情况相反,而在其他语言中情况相同。

我的问题可以分为两个不同的问题:

  • 在 Java 中,类的静态变量是在运行时创建的还是在编译时创建的?
  • 在 Java 中,类的 final static 变量是在运行时还是编译时创建的?

编译时间与运行时间的区别:

  • 编译时间:编译源代码时(即创建 .class 文件时)
  • 运行时间:程序真正运行的时候

部分代码仅用于本题:

// 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

如果 staticfinal static 变量都将在运行时创建,那么在 Main 的第一个版本中,MyClass 类的两个静态变量(实例和 PI)都不会被创建。但我希望 final static 变量 PI 会在编译时创建(因此它将“嵌入”在 .class 文件中)因为我认为这会有更好的性能(无论 MyClass 类发生什么情况,PI 将始终为 3.14159265359,因此最好将其放入二进制文件中。
这可能与静态变量相同,但它可能会在整个程序中发生变化。

最佳答案

In Java, are static variables of a class created at run time or at compile time?

在 Java 中,编译时不会“创建”任何变量,如果创建是指分配和初始化。它们都是在运行时创建的。它们是 static 还是 static final何时它们被分配无关。

But I would kind of expect that the final static variable PI would be created at compile time (so it would be "embedded" in the .class-file) because I think this would have a better performance...

这不是它在 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 timeoutMillisString DEFAULT_HEADER)都是在运行时完成的。

If both static and final static variables would be created at run time, in the Main's first version neither of both static variables (instances and PI) of class MyClass would be created.

在您的示例中,static 字段(final 或不是)在类第一次加载 时分配和初始化。因此,在您的第一个 Main 中,永远不会像您提到的那样创建 instancesPI static 字段。在你的第二个例子中。一旦引用了 MyClass,就会加载类文件并创建 static 字段。

关于java - Java 中如何处理 static final 和 static 成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54754387/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com