在子类构造对象时,发现访问子类构造函数时,父类也运行了。
为什么呢?
因为:在子类的构造函数中,第一行有一个默认的隐式语句 -----> super();
//调用的是父类中空参数的构造函数
而子类的构造函数(无论有 还是无参),第一行的默认隐式语句都是super();
为什么子类实例化的时候要访问父类中的构造函数呢?
子类继承父类,获取到了父类中的内容(属性),所以在使用父类内容之前,要先看父类是如何对自己的内容进行初始化的,所以子类在构造对象时,必须访问父类中的构造函数。
为了完成这个必须的动作,就在子类的构造函数中加入了super()语句。
如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中的哪个构造函数。同时子类的构造函数中,如果使用this调用本类构造函数时,super就没有了。因为super和this都只能定义第一行。所以只能有一个。但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。
这里需要注意的是:super语句必须定义在子类构造函数的第一行。因为父类的初始化动作要先完成。
子类对象初始化必须访问至少一个父类。
注意--->没有父类的情况下:先默认初始化,再构造函数初始化,然后再显示初始化,
但是有父类的情况下:通过super初始化父类内容时,子类的成员变量并未显示初始化,而是默认初始化0。等super()父类初始化完毕后,才进行子类的成员变量显示初始化8。
一个对象实例化过程:
Person p = new Person();
- jvm会读取指定的路径下的Person.class文件,并加载进内存,并会先加载person的父类(如果有直接的父类的情况下)。
- 在堆内存中的开辟空间,分配地址。
- 并在对象空间中,对对象中的属性进行默认初始化。
- 调用对应的构造函数进行初始化。
- 在构造函数中,第一行会先调用父类中构造函数进行初始化。
- 父类初始化完毕后,在对子类的属性进行显示初始化。
- 在进行子类构造函数的特定初始化。
- 初始化完毕后,将地址值赋给引用变量。
Ps:引用变量不一定在栈内
Class demo{
Person p = new Person();//在堆内,成员变量。
}