初始化时机
初始化分为类变量的初始化与对象的初始化两个相对独立的过程
- 类变量的初始化在程序中第一次用到该类时
类变量的初始化过程:首先将静态变量定义时的初始化语句放到静态初始化块的开始部分,然后从该类的原始祖先开始依次向下执行每个类的静态初始化块 - 对象的初始化发生在创建对象时
对象的初始化过程会先将类的定义成员变量时的初始化语句及非静态初始化块都放到构造函数的开始部分,然后从该类的原始祖先开始依次向下执行每个类的构造函数
初始化谜题
类的定义过程中创建对象
- 在main中遇到Demo,执行类变量demo初始化,
new Demo()
引起对象初始化过程 - 对象初始化过程首先将
int y = 1
放到Demo构造函数开始部分,所以结果中 y =1 - 但是注意
static int x =1
句并没有被执行,因此此时 x =0 - 类变量demo初始化完成,然后执行类变量 x的初始化 x=1
- 最后输出Demo.x,此时x已初始化完成, 所以 x = 1
public class Demo {
static Demo demo = new Demo();
static int x = 1;
int y = 1;
Demo() {
System.out.println(x);
System.out.println(y);
}
public static void main(String[] args) {
System.out.println(Demo.x);
}
} //结果:0 1 1
循环初始化
-
new Demo()
句引起执行对象初始化 - 对象初始化首先会将
Demo demo = new Demo()
句置于构造函数的开始部分 - 在执行移入构造函数内部的
Demo demo = new Demo()
句时引起死循环调用构造函数,从而引起StackOverflowError
public class Demo {
Demo demo = new Demo();
Demo() {
}
public static void main(String[] args) {
System.out.println(new Demo());
}
} // 结果:StackOverflowError