类和对象的初始化顺序是面试中常考的一个题目。
如果了解类加载机制,应该知道实例化过程中的执行顺序:1)类变量初始化;2)类变量赋初值/静态块;3)对象变量初始化;4)对象变量赋初值;5)构造函数。
需要注意的是,变量初始化与赋初值的区别:
1) 成员变量初始化是实例化之初为变量分配空间使之存在,并设定缺省值(0,null等)。
2) 赋初值是通过一条赋值语句为成员变量人为的赋值,也是第一次赋值。
3) 成员变量的赋初值是发生在所有成员的初始化之后,构造函数之前。
如下面例子中:
public class Initialization {
private Inner inner = new Inner();
public Initialization() {
System.out.println("Initialization(), inner=" + inner);
}
class Inner {
public Inner() {
System.out.println("Inner(),inner=" + inner);
}
}
public static void main(String[] args) {
new Initialization();
}
}
其输出结果为:
Inner(),inner=null Initialization(), inner=Initialization$Inner@c17164
如果涉及多个类之间的关系,比如继承、委托等。初始化顺序就变得比较复杂了。
我们可以借助类图做分析,比如下面的类图中,其实也暗含了类和对象的初始化顺序。
IsA既表示静态关系(类相关)又表示动态关系(对象相关),HasA表示动态关系。
类和对象的初始化顺序遵循以下两条规则:
1)静态关系先行,动态关系后行。
2)箭头所指的类/对象在先,箭尾的类/对象在后。