java中的初始化顺序,静态块内的构造函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中的初始化顺序,静态块内的构造函数相关的知识,希望对你有一定的参考价值。
考虑到标准的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)从那里,它应该是显而易见的。
以上是关于java中的初始化顺序,静态块内的构造函数的主要内容,如果未能解决你的问题,请参考以下文章
java学习之静态块显示初始化块构造函数this在构造函数中的调用,区别联系与调用顺序