父类
public class Father {
static{
System.out.println("父类静态代码块");
}
{
System.out.println("父类非静态代码块");
}
Father() {
System.out.println("父类构造方法");
}
}
子类
public class Son extends Father {
static{
System.out.println("子类静态代码块");
}
{
System.out.println("子类非静态代码块");
}
Son() {
System.out.println("子类构造方法");
}
}
测试类
public class Test {
public static void main(String[] args) {
new Father();
new Son();
}
}
先猜一猜 执行顺序是什么?
有的同学可能会说结果是
父类静态代码块
父类非静态代码块
父类构造方法
父类静态代码块
子类静态代码块
父类非静态代码块
父类构造方法
子类非静态代码块
子类构造方法
结果:
父类静态代码块
父类非静态代码块
父类构造方法
子类静态代码块
父类非静态代码块
父类构造方法
子类非静态代码块
子类构造方法
为什么呢?
因为: 子类初始化的时候会先初始化父类。 而静态代码块会在类加载的时候调用,并且只会调用一次。而非静态代码块是类初始化的时候调用,并且是在构造方法前调用。
执行顺序为: 父类静态代码块 》 父类非静态代码块 》 父类构造方法 》子类静态代码块 》子类非静态代码块 》子类构造方法
如果换一种写法,结果又不一样了:
public class Test {
public static void main(String[] args) {
// new Father();
new Son();
}
}
结果是什么呢?可以先猜一下
公布答案:
父类静态代码块
子类静态代码块
父类非静态代码块
父类构造方法
子类非静态代码块
子类构造方法
你猜对了吗?
其实要捋明白很简单,就记着静态代码块一定先执行,并且只执行一次。 要有孩子肯定要现有爹,但是呢,不管是爹还是儿子,非静态代码块要在构造函数前执行。可以理解为,非静态代码块是进手术室,构造方法是出生。 然后肯定是爹先出生,后有儿子,因此肯定是老爹先进手术室(调用父类非静态代码块)出生(调用父类构造方法),然后儿子进手术室(调用子类非静态代码块)出生(调用子类构造方法)