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
类之后,当它被初始化时,会发生以下事情:
-
static Test aStatic=new Test();
==>作为类TestLab
初始化的一部分调用。从这里,Test
类被引用。所以,控制移动到Test
类 -
static Test ref=new Test();
==>即,执行Test类的第一行(在其初始化阶段)。这一行涉及到创建一个Test
的新实例,因此控制转移到Test
的实例块( Test的实例块中),然后转移到构造函数( Test的默认构造函数)。 -
现在
static Test ref=new Test();
已经完成,因此,Test
的类初始化继续,到达静态块(In static block of Test)。Test
初始化完成 -
Control到达
TestLab
,现在new Test()
被调用。因此,再次In Test的实例块和 Test的默认构造函数被打印(类已经初始化,因此static
字段不会再次初始化,静态块也不会执行)。 -
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的实例,但是当提供实例块时,它将被执行,然后是构造函数,最后是静态块。