前言
Class类中有静态属性、代码块、非静态属性…等诸多元素时,如果不清楚各个元素的初始顺序,那么很有可能会写出一些匪夷所思的代码。正因为其如此重要,所以博主写了个例子,很容易就能知道他们的初始顺序
初始化顺序
话不多说,直接上代码:
class Display {
public static int parentStaticField() {
System.out.println("父类静态字段");
return 1;
}
public static int parentField() {
System.out.println("父类普通字段");
return 1;
}
public static int sonStaticField() {
System.out.println("子类静态字段");
return 1;
}
public static int sonField() {
System.out.println("子类普通字段");
return 1;
}
}
class Parent {
static {
System.out.println("父类静态代码块");
}
{
System.out.println("父类普通代码块");
}
public static int a = Display.parentStaticField();
public int b = Display.parentField();
static {
System.out.println("父类静态代码块2");
}
public Parent() {
System.out.println("父类构造函数");
}
{
System.out.println("父类普通代码块2");
}
}
class Son extends Parent {
static {
System.out.println("子类静态代码块");
}
{
System.out.println("子类普通代码块");
}
public static int c = Display.sonStaticField();
public int d = Display.sonField();
static {
System.out.println("子类静态代码块2");
}
public Son() {
System.out.println("子类构造函数");
}
{
System.out.println("子类普通代码块2");
}
}
public class ClassInitialOrder {
public static void main(String[] args) {
new Son();
}
}
输出结果:
父类静态代码块
父类静态字段
父类静态代码块2
子类静态代码块
子类静态字段
子类静态代码块2
父类普通代码块
父类普通字段
父类普通代码块2
父类构造函数
子类普通代码块
子类普通字段
子类普通代码块2
子类构造函数
由此可以看出,类初始化顺序为:
父类静态代码块/静态字段(按照定义顺序)=> 子类静态代码块/静态字段(按照定义顺序)=> 父类普通代码块/普通字段(按照定义顺序)=> 父类构造方法 => 子类普通代码块/普通字段(按照定义顺序)=> 子类构造函数
总结
需要注意的几点是:
- 静态代码块和静态字段只执行一次(不管父类还是子类)
- 静态代码比非静态代码先执行
- 代码块和字段执行的优先级就是定义的顺序,或者说代码编写的顺序
- 父类构造方法比子类普通代码块先执行
注意了以上四点,类的初始化应该就不是问题了。