静态变量何时初始化?

2022-08-31 10:24:30

我想知道静态变量何时初始化为其默认值。当加载类时,创建(分配)静态 vars,然后执行声明中的静态初始值设定项和初始化,这是正确的吗?在什么情况下给出默认值?这导致了前向引用的问题。

另外,请您参考为什么静态字段没有及时初始化?中提出的问题来解释这一点,特别是Kevin Brock在同一网站上给出的答案。我无法理解第三点。


答案 1

请参阅 Java 静态变量方法

  • 它是一个属于类而不是对象(实例)的变量
  • 静态变量在执行开始时只初始化一次。这些变量将首先初始化,然后再初始化任何实例变量
  • 由类的所有实例共享的单个副本
  • 静态变量可以通过类名直接访问,不需要任何对象。

如果实例和类(静态)变量未能有意初始化,它们将自动初始化为标准默认值。尽管局部变量不会自动初始化,但无法编译无法初始化局部变量或在使用前为该局部变量赋值的程序。

编译器实际执行的操作是在内部生成一个类初始化例程,该例程将所有静态变量初始值设定项和所有静态初始值设定项代码块(按它们在类声明中出现的顺序)组合在一起。此单个初始化过程在首次装入类时自动运行,仅运行一次。

对于内部类,它们不能具有静态字段

内部类是未显式或隐式声明的嵌套类。static

...

内部类不能声明静态初始值设定项 (§8.7) 或成员接口...

内部类不能声明静态成员,除非它们是常量变量...

请参阅 JLS 8.1.3 内部类和封闭实例

finalJava中的字段可以与其声明位置分开初始化,但是这不适用于字段。请参阅下面的示例。static final

final class Demo
{
    private final int x;
    private static final int z;  //must be initialized here.

    static 
    {
        z = 10;  //It can be initialized here.
    }

    public Demo(int x)
    {
        this.x=x;  //This is possible.
        //z=15; compiler-error - can not assign a value to a final variable z
    }
}

这是因为只有一个与类型关联的变量副本,而不是像实例变量那样与该类型的每个实例相关联的副本,如果我们尝试在构造函数中初始化类型,它将尝试重新初始化类型字段,因为构造函数在静态字段不得出现的类的每个实例化上运行。staticzstatic finalstatic finalzfinal


答案 2

当类装入器装入类时,将初始化静态字段。此时分配默认值。这是按照它们在源代码中出现的顺序完成的。