类成员和函数的执行顺序
先看下面代码
public class RunOrderTest {
public static void main(String[] args) {
Animal animal = new Dog();
}
}
class Animal {
public static String type = "父类";
public String name = "Animal";
public int age;
static {
System.out.println("Animal static init fun :" + type);
}
{
System.out.println("Animal init fun");
}
public Animal() {
System.out.println("Animal 构造函数");
a();
}
public void a() {
System.out.println("Animal a");
}
}
class Dog extends Animal {
public static String type = "子类";
public String name = "Dog";
public int age = 1;
static {
System.out.println("Dog static init fun :" + type);
}
{
System.out.println(this.name + " init fun " + this.sex);
}
public String sex = "1"; //在非静态初始化代码块之后
public Dog() {
super();
System.out.println("Dog 构造函数 age=" +age);
}
@Override
public void a() {
System.out.println(name + " a " + age);
}
}
请看函数a的打印结果,是否和你想的结构一致?
输出结果:
Animal static init fun :父类
Dog static init fun :子类
Animal init fun
Animal 构造函数
null a 0 //注意这里的age 被编译器初始化了默认值
Dog init fun null
Dog 构造函数 age = 1
由此看出:
1.在一个不存在继承的类中:
成员变量的初始化,在类的所有方法调用之前进行,包括构造方法。成员变量初始化则是按照定义顺序进行的。即:
–>初始化static变量, 执行static初始化快
–>初始化普通成员变量(如果有赋值语句), 执行普通初始化块(成员变量赋值和代码块顺序看代码定义顺序
)
–>构造方法
2. 在一个存在继承的类中:
–>初始化父类static成员变量,运行父类static初始化块
–>初始化子类static成员变量,运行子类static初始化块
–>初始化父类实例成员变量(如果有赋值语句),执行父类普通初始化块
–>父类构造方法
–>初始化子类实例成员变量(如果有赋值语句)及普通初始化块(成员变量赋值和代码块执行顺序看代码定义顺序
)
–>子类构造方法。
总结:
1.先初始化static 成员和 static代码块,先父类完全初始化后再执行子类
2.接着初始化成员变量和代码块(注意,如果成员变量有赋值语句,赋值顺序和代码块执行顺序视这二者代码定义顺序先后,初始化肯定是先成员变量 再初始化代码块,但初始化和赋值是二步操作,别混了)
再初始化 构造方法。
另外 对象的初始化是先父类完全初始化后(即包含变量、代码块、构造函数),才去初始化子类。