简体   繁体   English

Java静态最终字段初始化顺序

[英]Java static final field initialization order

I tried to understand the behavior of initialization order when static fields are initialized with a reference to the same enclosing class object. 我尝试了解通过引用同一封闭类对象初始化静态字段时的初始化顺序行为。

public class Test {

        static final Test t=new Test();
        static int a=5;

        Test(){
            System.out.println("a="+a);
        }

        public static void main(String[] args) {
            new Test();
        }

    }

Output of above piece of code is: 上面这段代码的输出是:

a=0
a=5

If I modify variable a to anything else other than plain static : 如果我将变量a修改为除纯static以外的其他值:

static final a=5;
a=5;
final a=5;

The output is: 输出为:

a=5
a=5

Why is this behavior? 为什么会这样呢?

Note that the output is a=5 & a=5 even when both t & a are declared as static final in which case t precedes the declaration of a 注意,输出是a=5 & a=5即使当t & a被声明为static final在这种情况下t之前的声明a

static final members are initialized before other static members. 静态最终成员在其他静态成员之前被初始化。

non final static members are initialized in order of appearance 非最终静态成员按出现顺序初始化

Therefore, in your first case : 因此,在您的第一种情况下:

    static Test t=new Test();
    static int a=5;

The constructor is first called before a is initialized, so a=0 is displayed. 构造函数首先被调用之前a被初始化,所以a=0被显示出来。

In the second case, static final a is initialized before t , so a=5 is displayed when the first instance of Test is created. 在第二种情况下, static final at之前初始化,因此a=5创建Test的第一个实例时显示a=5 When a is not static, it is initialized prior to the execution of the constructor, so again a=5 is displayed. a不是静态的时,它将在构造函数执行之前被初始化,因此再次显示a=5

Regarding the edit in your question. 关于您的问题中的编辑。

Looking at section 12.4.2 of the JLS : 查看JLS的12.4.2节:

  1. Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28). 然后,初始化其最终值是编译时常量表达式的接口的最终类​​变量和字段(第8.3.2.1,第9.3.1,第13.4.9,第15.28节)。

... ...

  1. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block. 接下来,以文本顺序执行类的类变量初始化器和静态初始化器,或者接口的字段初始化器,就好像它们是单个块一样。

You see that final class variables (ie static final) are initialized before the rest of the static variables only if their values are compile time constant expressions . 您会看到,仅当final类变量(即static final)的值是编译时常量表达式时,它们才在其余静态变量之前初始化。 5 is a constant expression. 5是一个常数表达式。 new Test() is not. new Test()不是。 Therefore a is initialized before t even if both are static final. 因此,即使两个都是静态最终值, a也会在t之前初始化。

Static variables are initialized when the class gets loaded by class loader. 当类加载器加载类时,将初始化静态变量。 So when first line “static Test t=new Test();” gets executed, the value of int “a” is not yet initialized, hence it is showing as 0. But other 3 cases (ie removing static, adding final or without any modifier) what happens a gets initialized at the time of Object creation of Test class, which is happening in the first line so it is showing the value “5”. 因此,当执行第一行“ static Test t = new Test();”时,int“ a”的值尚未初始化,因此显示为0。但是其他3种情况(例如,删除static,添加final或不添加static)任何修饰符)在Test类的对象创建时会发生什么初始化,这发生在第一行中,因此它显示值为“ 5”。

Java Language specification is best source to understand all about initialization order. Java语言规范是了解所有有关初始化顺序的最佳信息。 According to that in your scenario, static final field gets initialized before any class level variable gets initialized. 根据您的情况,在初始化任何类级变量之前,将初始化static final字段。 When you remove the final, initialization was deferred. 当您删除最终版本时,初始化被推迟。 It should also be noted if you change 如果更改,也应注意

static Test t=new Test();
static int a=5;

to

  static int a=5;
  static Test t=new Test();

it will also print 它也会打印

 a = 5
 a = 5

because of initialization order. 因为初始化顺序。

static final a=5 It is final so it initialize first, before other static members or methods. static final a=5这是final因此它先初始化,再初始化其他静态成员或方法。

In first scenario main() method get executed first and it initialize a to its default value 0 . 在第一种情况下, main()方法首先执行,并将a初始化为其默认值0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM