packagecom.itheima.stu.exam;
classX{
Y b=newY();
X(){
System.out.println("X");
}
}
classY{
Y(){
System.out.println("Y");
}
}
publicclassZextendsX{
Y y=newY();
Z(){
super();
System.out.println("Z");
}
publicstaticvoidmain(String[]args){
newZ();
}
}
1.new Z();先要为Z开辟内存空间,创建属性Y y 此时y的值为null,
接着调用Z的构造方法,因为在构造方法内部有隐含的super(),所以先调用父类的
构造方法,因为父类中有属性Y b 初始时为null,所以先为b进行显示初始化,执行
new Y();此时调用Y的构造方法,打印Y
2.接着调用父类的构造方法X();输出X
上面说明父类:要先进行成员变量的显示初始化,在进行构造方法的初始化
3.为子类的成员变量y赋值,执行new Y();调用Y的构造方法,输出 Y
4.执行子类Z中调用super()语句后的语句,输出Z
所以答案为YXYZ
总结:不管是子类还是父类都要先执行成员变量的显示初始化,再执行构造方法初始化
=================================================================================
packagecom.itheima.stu.extend;
classFatherextendsObject{
publicFather(){
//super();
System.out.println("Father 的构造方法");
}
}
classSonextendsFather{
publicSon(){
super();//这是一条语句,如果不写,系统会默认加上,用来访问父类中的空参构造
System.out.println("Son 的构造方法");
}
}
publicclassDemo5_Extends{
publicstaticvoidmain(String[]args){
Sons=newSon();
}
}
随着知识难度加大,还请老师多费心基础差点的学生.
遇到稍微复杂点的问题后听起来还是有点吃力希望能够在讲的细一点
希望课间给我们一些,有功底的学员更多的解答些其它Java技术上的问题
以前没有基础,学到后面感觉吃力,班里学习能力也程差不齐,能多照顾一下基础薄弱的同学最
好了,当然自己也要多努力.
==================================================================================
packagecom.itheima.stu.exam;
/*
* 结果:Y1X1W1Z1
* */
classX1{
Y1 b=newY1();
X1(){
//System.out.println(this.getClass().getSimpleName()+"------------------");
System.out.println("X1");
}
static{
System.out.println("加载X1类");
}
}
classY1{
Y1(){
//System.out.println(this.getClass().getSimpleName()+"...............");
System.out.println("Y1");
}
}
classW1{
W1(){
//System.out.println(this.getClass().getSimpleName()+"...............");
System.out.println("W1");
}
}
publicclassZ1extendsX1{
W1 w1=newW1();
Z1(){
super();
System.out.println("Z1");
}
publicstaticvoidmain(String[]args){
newZ1();
}
static{
System.out.println("加载Z1类");
}
}
对上述代码通过debug的总结:
1.该代码保存的文件名为"Z1",我们编译时执行的是javac Z1.java,运行的是java Z1,
此时要加载Z1,但是发现Z1有父类X1,所以要先加载X1类,而X1类中有静态代码块,所以输出"加载X1类"
注意:类的加载是为以后的使用做准备的,并不是加载的时候就执行类中的所有内容,只有类中的静态代码块在加载的时候才被执行,而且只执行一次
2.父类X1加载完毕后要加载子类Z1,而子类Z1中也有静态代码块,所以要执行子类Z1的静态代码块,所以输出"加载Z1类"
3.父类和子类加载完毕后,找到Z1类中的main方法,然后main方法进栈内存要执行,而此时第一句话是new Z1();表示要创建子类的Z1对象,
此时不会先执行子类的成员变量赋值和构造代码块,而是先执行super();通知父类X1做初始化工作,而父类中如果有成员变量和构造代码块(它俩属于同一级别,按先后顺序执行)的话要先执行,
而这里有成员变量的初始化Y1 b = new Y1();所以要调用Y1的构造方法,输出"Y1",接着执行父类X1的构造方法输出"X1",此时父类初始化工作完成
4.给子类Z1的成员变量W1 w1 = new W1();初始化,执行new W1();所以调用W1的构造方法,输出"W1",接下来说明super执行完毕,执行super之后的语句输出"Z1"
==================================================================================
classW{
{
System.out.println("W的构造代码块......10");
}
static{
System.out.println("W的静态代码块......9");
}
W(){
System.out.println("W的空参构造函数....11");
}
}
classY{
{
System.out.println("Y的构造代码块.....4");
}
static{
System.out.println("Y的静态代码块.....3");
}
Y(){
System.out.println("Y的空参构造函数....5");
}
}
classX{
Y b=newY();
{
System.out.println("X的构造代码块.....6");
}
static{
System.out.println("X的静态代码块.....1");
}
X(){
System.out.println("X的空参构造函数....7");
}
}
publicclassZextendsX{
{
System.out.println("Z的构造代码块......8");
}
static{
System.out.println("Z的静态代码块......2");
}
Z(){
super();
System.out.println("Z的空参构造函数....12");
}
W w=newW();
publicstaticvoidmain(String[]args){
newZ();
}
}
关于上面的代码的运行流程:
1.此代码文件保存为"Z"(有main方法),而Z继承了X,所以首先加载X类,而在X类中有静态代码块,所以输出"X的静态代码块.....1"
2.加载类Z,因为Z中有静态代码块,所以输出"Z的静态代码块......2"
3.执行Z的空参构造函数中super()通知父类进行初始化操作,而在父类(X类)中有引用类型的成员变量、构造代码块(它们俩按照先后顺序执行)、构造方法
a.为X类中引用变量b执行初始化操作,b=new Y();此时要加载类Y
(1)加载类Y执行Y类中的静态代码块,所以输出"Y的静态代码块.....3"
(2)执行Y类中的构造代码块,所以输出"Y的构造代码块.....4"
(3)执行Y类中的空参构造函数,所以输出"Y的空参构造函数....5"
b.执行X类中的构造代码块,所以输出"X的构造代码块.....6"
c.执行X类中的构造函数,所以输出"X的空参构造函数....7"
4.父类初始化完毕(包括成员变量、构造代码块(它俩按照代码中的先后顺序执行)、构造函数)后,并不会直接执行super()后面的内容,而是要对子类Z按照上面的
顺序进行初始化(包括成员变量、构造代码块(它俩按照代码中的先后顺序执行)、构造函数)
a.子类X构造代码块在上面,所以先执行,输出"Z的构造代码块......8"
b.为Z类Z的成员变量w赋值w=new W(),所以要现加载W
(1)加载类W,执行其中的静态代码块,所以输出"W的静态代码块......9"
(2)创建W的对象,所以先执行W的构造代码块,输出"W的构造代码块......10"
(3)执行W的构造方法,所以输出"W的空参构造函数....11"
c.接着执行super()后面的内容,所以输出"Z的空参构造函数....12"
==================================================================================
案例:
classDemo5_Extends{
publicstaticvoidmain(String[]args){
Sons=newSon();
}
}
classFatherextendsObject{
A a=newA();
{
System.out.println("........6");
}
publicFather(){
super();
System.out.println("Father 的构造方法....7");
}
static{
System.out.println(".....1");
}
}
classSonextendsFather{
B b=newB();
{
System.out.println("..........11");
}
publicSon(){
super();
System.out.println("Son 的构造方法.....12");
}
static{
System.out.println(".....2");
}
}
classA{
static{
System.out.println("A.............3");
}
{
System.out.println("A构造代码块.........4");
}
publicA(){
System.out.println("A空参构造方法执行..........5");
}
}
classB{
static{
System.out.println("B.............8");
}
{
System.out.println("B构造代码块.........9");
}
publicB(){
System.out.println("B空参构造方法执行..........10");
}
}
1.加载class文件时,如果有继承关系,要先加载父类的class文件
2.子类初始化之前,要先完成父类的初始化
3.成员变量(引用型)的初始化和和构造代码块的初始化,谁在前谁先执行