考虑到标准的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
因此,只要类加载器加载了类,静态块就会执行。所以,你的第一个静态块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) {}
}
JLS说
在您的示例中,第一个静态创建Foo
的实例。这会导致在执行第一个静态块时执行Foo
的实例块。所以,顺序是:
Foo
的静态初始化new Foo()
。
执行实例块 - 打印“非静态代码”
执行构造函数 - 打印“构造函数”好吧,要重构代码,请执行以下步骤:
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)从那里,它应该是显而易见的。