当创建任何Java对象时,程序总会依次调用每个父类非静态初始化块/父类构造器执行初始化,最后调用本类的非静态初始化块/构造器执行初始化。
输出结果:
一 隐式调用和显式调用
当调用某个类的构造器来创建Java对象时,系统总会调用父类的非静态初始化块进行初始化。这个调用是隐式执行,而且父类的静态初始化块总是会被执行。接着会调用父类的一个或多个构造器执行初始化,这个调用既可以通过super进行显式调用,也可以是隐式调用。
当所有父类的非静态初始化块/构造器依次调用完成后,系统调用本类的非静态初始化块/构造器执行初始化,最后返回本类的实例。
(Java程序里所有类的最终父类都是java.lang.Object类)
我们来看下面的例子:
public class Creater {
{
System.out.println("Creater的非静态初始化块");
}
public Creater(){
System.out.println("Creater无参构造");
}
public Creater(String name){
this();
System.out.println("Creater带有参数的name构造器"+name);
}
}
/**
* 子类
*/
public class Animal extends Creater {
{
System.out.println("Animal的非静态初始化块");
}
public Animal(String name){
super(name);
System.out.println("Animal的有参构造器"+name);
}
public Animal(String name,int age){
this(name);
System.out.println("Animal带两个参数的构造器"+name+age);
}
}
/**
* 继承Animal的子类
*/
public class Wolf extends Animal {
{
System.out.println("Wolf的非静态初始化块");
}
public Wolf() {
super("灰太狼",3);
System.out.println("Wolf的无参构造器");
}
public Wolf(double weight){
this();
System.out.println("Wolf带参的构造器"+weight);
}
}
调用:
public class Test {
public static void main(String[] args){
new Wolf(2.5);
}
}
Creater的非静态初始化块
Creater无参构造 (总父类初始化)
Creater带有参数的name构造器灰太狼
Animal的非静态初始化块
Animal的有参构造器灰太狼<span style="white-space:pre"> </span>(wolf的父类初始化)
Animal带两个参数的构造器灰太狼3
Wolf的非静态初始化块
Wolf的无参构造器<span style="white-space:pre"> </span>(wolf初始化)
Wolf带参的构造器2.5
只要在程序中创建Java对象,系统总是先调用最顶层的父类初始化操作,包括初始化块和构造器,然后依次向下调用所有父类的初始化操作,最终执行本类的初始化操作返回本类的实例。
至于调用父类的哪个构造器执行初始化,则分为如下几种情况:
1子类构造器执行体的第一行代码使用super显式调用父类的构造器,系统将根据super调用里传入的实参列表来确定调用父类的哪个构造器。
2子类构造器执行体的第一行代码使用this显式调用本类中重载的构造器,系统将根据this调用里传入的实参列表来确定本类的另一个构造器(执行本类中另一个构造器时即进入第一种情况)
3子类构造器执行提中既没有super调用,也没有this调用,系统将会在执行子类的构造器之前,隐式调用父类无参数构造器。
super调用用于显式调用父类的构造器,this调用用于显式调用本类中另一个重载的构造器。super和this调用都只能在构造器中使用,而super和this调用都必须作为构造器的第一行代码,因此构造器中的super调用和this调用最多只能使用其中之一,而且最多只能调用一次。