This question already has answers here:
Java order of Initialization and Instantiation
(2个答案)
4年前关闭。
我正在准备Java OCA考试。上面的代码摘自我正在研究的书。根据答案,结果应该是
虽然我希望它是
考虑以下规则:
静态初始化块在首次加载类时运行
正常的初始化块在所有超级构造函数运行后立即运行
有人可以一步一步告诉我这是怎么发生的吗?我可以理解
(2个答案)
4年前关闭。
class Bird {
{
System.out.print("b1 ");
}
public Bird() {
System.out.print("b2 ");
}
}
class Raptor extends Bird {
static {
System.out.print("r1 ");
}
public Raptor() {
System.out.print("r2 ");
}
{
System.out.print("r3 ");
}
static {
System.out.print("r4 ");
}
}
class Hawk extends Raptor {
public static void main(String[] args) {
System.out.print("pre ");
new Hawk();
System.out.println("hawk ");
}
}
我正在准备Java OCA考试。上面的代码摘自我正在研究的书。根据答案,结果应该是
r1 r4 pre b1 b2 r3 r2 hawk
虽然我希望它是
pre r1 r4 b1 b2 r3 r2 hawk
考虑以下规则:
静态初始化块在首次加载类时运行
正常的初始化块在所有超级构造函数运行后立即运行
有人可以一步一步告诉我这是怎么发生的吗?我可以理解
r1
和r4
排在一切之前,但是为什么pre
在它们之后? 最佳答案
加载类Hawk
时,还必须加载类Raptor
和Bird
,因为它们(作为超类)是Hawk
定义的一部分。加载类后,将运行静态初始化程序。 “静态”实际上只是意味着它是类的一部分,而不是类的实例。
JVM的下一步是开始执行main
方法。它是静态的,因此尚未创建任何实例。这就是为什么下一个打印“ pre”的原因。
然后main方法创建Hawk
的实例,该实例将调用构造函数。在输入构造函数方法之前,将按文件中的顺序执行非静态初始化器块以及字段初始化(这些类没有任何初始化)。
之后,它会打印“鹰”并退出。
PS。在编写代码时,我避免使用初始化程序块。当所有语句都在构造方法中时,更容易阅读代码并在以后理解它。一个例外是构建常量集合(即Maps),因为Java否则实际上并不支持它(与文字映射/字典/对象的Python或JavaScript语法不同)。
10-05 19:13