考虑到标准的Java初始化顺序规则,我不清楚为什么下面的代码
public class Foo {
static { new Foo(); }
static{ System.out.println("static code"); }
{ System.out.println("non static code"); }
public Foo() { System.out.println("constructor"); }
public static void main(String[] args) {}
}
输出以下内容:
non static code
constructor
static code
答案 0 :(得分:1)
因此,静态加载块将在类加载器加载类后立即执行。因此,您的第一个静态块static { new Foo(); }
首先执行,这进一步调用了构造函数new Foo();
。按照Java docs,非静态块将由编译器复制到每个构造函数,这意味着System.out.println("non static code");
将被复制到构造函数public Foo() { System.out.println("constructor"); }
。因此,它将先打印non static code
,然后再打印constructor
。在执行完第一个静态块之后,它将执行第二个静态块,并输出最后一个static code
。
编译后,您的代码类似于以下代码:
public class Foo {
static { new Foo(); }
static{ System.out.println("static code"); }
public Foo() {
System.out.println("non static code");
System.out.println("constructor");
}
public static void main(String[] args) {}
}
答案 1 :(得分:1)
JLS表示
初始化类时,将按程序源代码顺序执行静态块和静态变量初始化。
实例初始化时,将按程序源代码顺序执行实例块和实例变量初始化。在超级实例初始化之后之后和在构造函数主体执行之前 发生这种情况。
在您的示例中,第一个静态对象创建Foo
的实例。这导致Foo
的实例块在执行第一个静态块的同时 被执行。因此,顺序为:
Foo
的静态初始化已触发new Foo()
。
答案 2 :(得分:0)
要重构代码,请执行以下步骤:
1)删除非静态初始化块-编译器在实际构造函数中的代码之前放置
public class Foo {
static { new Foo(); }
static{ System.out.println("static code"); }
public Foo() {
System.out.println("non static code");
System.out.println("constructor");
}
public static void main(String[] args) {}
}
2)加入静态初始化块-参见here:
一个类可以具有任意数量的静态初始化块,并且它们 可以出现在班级正文中的任何位置。运行系统保证 静态初始化块的顺序是: 出现在源代码中。
public class Foo {
static {
new Foo();
System.out.println("static code");
}
public Foo() {
System.out.println("non static code");
System.out.println("constructor");
}
public static void main(String[] args) {}
}
3)从那里应该很明显。