当使用静态引用创建对象时,为什么实例块和默认构造函数在静态块之前执行?


public class TestLab {
    static Test aStatic=new Test();
    public static void main(String[] args) {
        TestLab obj=new TestLab();
    }
    static{
        System.out.println("In static block of TestLab");
          }
}

public class Test {

    static Test ref=new Test();
    Test()
    {
        System.out.println("Default Constructor of Test");
    }
    static
    {
        System.out.println("In Static Block of Test");
    }
    {
         System.out.println("In instance block of Test");
    }
}

通常静态块在类加载期间首先执行。当执行上面的示例时,接收到以下输出:

Test

的实例块

Test的默认构造函数

Test静态块

Test

的实例块

Test的默认构造函数

TestLab的静态块

为什么测试类的实例块和默认构造函数在测试类的静态块之前执行?

好的。static字段/块在类初始化期间设置/执行。按照在代码中出现的顺序执行。因此,在加载TestLab类之后,当它被初始化时,会发生以下事情:

  1. static Test aStatic=new Test(); ==>作为类TestLab初始化的一部分调用。从这里,Test类被引用。所以,控制移动到Test

  2. static Test ref=new Test(); ==>即,执行Test类的第一行(在其初始化阶段)。这一行涉及到创建一个Test的新实例,因此控制转移到Test的实例块( Test的实例块中),然后转移到构造函数( Test的默认构造函数)。

  3. 现在static Test ref=new Test();已经完成,因此,Test的类初始化继续,到达静态块(In static block of Test)。Test初始化完成

  4. Control到达TestLab,现在new Test()被调用。因此,再次In Test的实例块和 Test的默认构造函数被打印(类已经初始化,因此static字段不会再次初始化,静态块也不会执行)。

  5. Control到达TestLab静态块(In TestLab静态块)

类型初始化时,按文本顺序执行所有静态初始化式和所有静态字段初始化式。源自JLS 12.4.2:

接下来,按文本顺序执行类变量初始化器和类的静态初始化器,或者接口的字段初始化器,就像它们是单个块一样。

换句话说,执行以下代码:

ref = new Test();
System.out.println("In Static Block of Test");

第一行创建了一个实例…这需要运行实例初始化器。所有实例初始化都发生在控制返回到类型初始化部分之前——也就是说,在静态初始化器运行之前。

如果您将字段声明移动到静态初始化器之后的,您将看到相反的结果。

通常static variables/blocks将按照它们定义的顺序初始化,这里您将aStatic标记为static。它将尝试通过调用构造函数来创建Test的实例,但是当提供实例块时,它将被执行,然后是构造函数,最后是静态块。

最新更新