谁能解释为什么这两种代码都按此顺序打印输出的原因(静态关键字执行优先级)
Could anyone explain the reason why output is printed in this order for both the codes(Static keyword execution priority)
代码 1:
public class test {
static {System.out.println("I am here in static");}
public test()
{
System.out.println("I am here in constructor");
}
public static void main(String[] args)
{
System.out.println("I am here in Main");
test staticCheck=new test();
}
输出 1:
我在这里静态
我在这里主要
我在构造函数中
代码 2:
public class test {
{System.out.println("I am here in static");}
public test()
{
System.out.println("I am here in constructor");
}
public static void main(String[] args)
{
System.out.println("I am here in Main");
test staticCheck=new test();
}
}
输出 2:
我在这里主要
我在这里静态
我在构造函数中
因为写CODE 2的人都是骗子
CODE 2 中的“I am here in static”应该改为“I am here in instance initialization block”。 IIBs 运行 每次在构造函数之前初始化实例。
更多内容见this tutorial。
在代码 1 中,行 static {System.out.println("I am here in static");}
是一个 静态初始化 块(也称为 静态初始化程序)。静态初始化程序块是用大括号 { } 括起来的普通代码块,前面有 static 关键字。这些块用于解决特定 class 在调用构造函数之前 可能具有的依赖项。将它们视为先决条件。因为 static 成员属于 class 而不是对象(实例),所以必须在创建任何实例之前加载它们(发生一次)。
在代码 2 上,当关键字 static 被移除时,该块变为 Initializer 块。初始化程序块类似于静态初始化程序,除了它们必须发生在创建 class 实例的过程中。因此,它们将在每个创建的实例中执行一次。因此,如果您要向 main
方法添加另一行以创建 test
的第二个实例,您的输出将是:
I am here in Main
I am here in static
I am here in constructor
I am here in static
I am here in constructor
请注意“我在静态中”和“我在构造函数中”出现了两次(每个实例一次)并且初始化程序块在构造函数之前执行。这些初始化程序块的使用不是很普遍,但在您有一系列可以由 class 的所有构造函数共享的指令的情况下,它们很有用。你可以看到为什么很少使用它。
如果我们重新添加 static 关键字,创建了两个对象的程序的输出将是:
I am here in static
I am here in Main
I am here in constructor
I am here in constructor
正如我之前提到的,因为初始化器现在是 static 它只出现一次。
“I am here in Main”和“I am here in constructor”的执行顺序不需要解释。但是,以防万一,因为这是它们在 main
方法中出现的顺序:System.out.println("I am here in Main")
发生在 staticCheck
对象被实例化之前。
UPDATE:这有点超出范围,但相关。如果要将父级 class 添加到此处显示的 class,则执行顺序如下:
- 打印父class静态初始化器
的内容
- 打印出这个class(子)静态初始化器的内容
- 打印出“我在 Main 这里”
- 打印父class(如果有的话)的非静态初始值设定项
- 打印父构造函数的内容
- 打印出这个(子)的非静态初始值设定项class
- 打印出这个class构造函数的内容
代码 1:
public class test {
static {System.out.println("I am here in static");}
public test()
{
System.out.println("I am here in constructor");
}
public static void main(String[] args)
{
System.out.println("I am here in Main");
test staticCheck=new test();
}
输出 1: 我在这里静态 我在这里主要 我在构造函数中
代码 2:
public class test {
{System.out.println("I am here in static");}
public test()
{
System.out.println("I am here in constructor");
}
public static void main(String[] args)
{
System.out.println("I am here in Main");
test staticCheck=new test();
}
}
输出 2: 我在这里主要 我在这里静态 我在构造函数中
因为写CODE 2的人都是骗子
CODE 2 中的“I am here in static”应该改为“I am here in instance initialization block”。 IIBs 运行 每次在构造函数之前初始化实例。
更多内容见this tutorial。
在代码 1 中,行 static {System.out.println("I am here in static");}
是一个 静态初始化 块(也称为 静态初始化程序)。静态初始化程序块是用大括号 { } 括起来的普通代码块,前面有 static 关键字。这些块用于解决特定 class 在调用构造函数之前 可能具有的依赖项。将它们视为先决条件。因为 static 成员属于 class 而不是对象(实例),所以必须在创建任何实例之前加载它们(发生一次)。
在代码 2 上,当关键字 static 被移除时,该块变为 Initializer 块。初始化程序块类似于静态初始化程序,除了它们必须发生在创建 class 实例的过程中。因此,它们将在每个创建的实例中执行一次。因此,如果您要向 main
方法添加另一行以创建 test
的第二个实例,您的输出将是:
I am here in Main
I am here in static
I am here in constructor
I am here in static
I am here in constructor
请注意“我在静态中”和“我在构造函数中”出现了两次(每个实例一次)并且初始化程序块在构造函数之前执行。这些初始化程序块的使用不是很普遍,但在您有一系列可以由 class 的所有构造函数共享的指令的情况下,它们很有用。你可以看到为什么很少使用它。
如果我们重新添加 static 关键字,创建了两个对象的程序的输出将是:
I am here in static
I am here in Main
I am here in constructor
I am here in constructor
正如我之前提到的,因为初始化器现在是 static 它只出现一次。
“I am here in Main”和“I am here in constructor”的执行顺序不需要解释。但是,以防万一,因为这是它们在 main
方法中出现的顺序:System.out.println("I am here in Main")
发生在 staticCheck
对象被实例化之前。
UPDATE:这有点超出范围,但相关。如果要将父级 class 添加到此处显示的 class,则执行顺序如下:
- 打印父class静态初始化器 的内容
- 打印出这个class(子)静态初始化器的内容
- 打印出“我在 Main 这里”
- 打印父class(如果有的话)的非静态初始值设定项
- 打印父构造函数的内容
- 打印出这个(子)的非静态初始值设定项class
- 打印出这个class构造函数的内容