Java 中如何处理静态最终成员和静态成员?

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

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

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

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

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

我的意思是编译时间与运行时间:

  • 编译时间:编译源代码的时间(即创建 .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

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

这可能与静态变量相同,但它可能会在整个程序中发生变化。


MMTTMM
浏览 131回答 1
1回答

莫回无

在Java中,类的静态变量是在运行时还是在编译时创建的?Java 在编译时没有“创建”变量,如果创建意味着分配和初始化。它们都是在运行时创建的。它们是否static与何时分配static final无关。但我有点期望最终的静态变量 PI 将在编译时创建(因此它将被“嵌入”在 .class 文件中),因为我认为这会有更好的性能......这不是它在 Java 中的工作方式。当类文件被“编译”时,它们实际上主要是被编码的。肯定有一些工作已经完成,但我们认为编译的超大比例(就 C 等语言而言)是在运行时发生的。当我们查看优化和内联时尤其如此。如果可能的话,编译器会做一些前期工作,例如能够提前预先计算字段(静态或实例)的值。例如,如果你像下面这样定义你的字段,那么乘法将在编译时完成:private long timeoutMillis = 10 * 24 * 3600 * 1000;对于 s 也是如此,String如果可能,编译器会将常量字符串附加在一起。以下内容在运行时不使用 a StringBuilder,而是String在编译时创建一个:private static final String DEFAULT_HEADER = "A long headers that is " +   "broker into two lines\n";但是,在这两种情况下,字段( thelong timeoutMillis和 the String DEFAULT_HEADER)的分配和初始化都是在运行时完成的。如果静态变量和最终静态变量都在运行时创建,那么在 Main 的第一个版本中,MyClass 类的两个静态变量(实例和 PI)都不会创建。在您的示例中,第一次加载static类时分配和初始化字段(final或不) 。因此,在您的第一个or字段中,永远不会像您提到的那样创建。在你的第二个例子中。一旦被引用,类文件将被加载并创建字段。MaininstancesPI staticMyClassstatic
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java