黑马程序员技术交流社区

标题: 已解决 关于继承中的运行顺序 [打印本页]

作者: 贾林栋    时间: 2012-8-17 13:43
标题: 已解决 关于继承中的运行顺序
本帖最后由 贾林栋 于 2012-8-18 11:19 编辑


                                                                                    “问题已经解决
现在明白了,谢谢大家!
class X1
{
X1()
{
  System.out.println("x1");
}
}
class X2
{
X2()
{
  System.out.println("x2");
}
}
class Y extends X1
{
Y()
{
  System.out.println("y");
}
}
class Z extends X2
{
Z()
{
  System.out.println("z");
}
  Y y=new Y();
  }
class  Demo1
{
public static void main(String[] args)
{
  new Z();  
}
}
上边代码的运行结果是:
x2
x1
y
z
为什么是这个结果?为什么最后才打印z?

作者: 金龙    时间: 2012-8-17 14:55
class X1
{
        X1()
        {
                System.out.println("x1");//打印了一个 x1
        }
}
class X2
{
        X2()
        {
          System.out.println("x2");                //3,打印了 x2
        }
}
class Y extends X1                //5,先加载父类 X1
{
        Y()
        {
          System.out.println("y");                //6,回到这里,打印了一个y
        }
}
class Z extends X2//2当读到这里,先加载父类进内存
{
        Z()
        {
          System.out.println("z");                        //7,成员变量初始化结束,开始给对象初始化。打印了z
        }
        Y y=new Y();        //4,加载完父类,回来后先给成员变量初始化,于是读Y
}
class  Demo1
{
        public static void main(String[] args)
        {
          new Z();  //1开始读Z
        }
}
作者: 黑马-郑鹏    时间: 2012-8-17 15:16
类初始化时构造函数调用顺序
1、初始化对象的存储空间为零或null值;
2、调用父类构造函数;
3、按顺序分别调用类成员变量和实例成员变量的初始化表达式;
4、调用本身构造函数

作者: 黑马-李勇    时间: 2012-8-17 15:39
------0607对象初始化过程
Person p=new Person("zhangsan",20);
该句话都做了什么事情?
1.因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。
2.执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3.在堆内存中开辟空间,分配内存地址。
4.在堆内存中建立对象的特有属性。并进行默认初始化。
5.对属性进行显示初始化。
6.对对象进行构造代码块初始化。
7.对对象进行对应的构造函数初始化。
8.将内存地址会给栈内存中的p变量。
所有初始化都做完了,才执行语句代码。

注意:
*******执行构造代码块和成员变量显示初始化时****
**********(代码中谁在前面谁就先执行)*********
作者: 胡文凡    时间: 2012-8-17 16:12
1. 初始化分为为的初始化和实例的初始化
2. 每个类在 JVM 中都对应一个 Class 实例
3. 父类实例是作为子例的部分存在的 (Class 实例之间也存在父子关系)
4. 初始化实例之前要初始化类

基于以上几点就可以理解以下初始化顺序
1. 父类静态属性、静态类 (父类的初始化,对应 JVM 方法 cinit())
2. 子类的静态属性、静态类 (子类的初始化,对应 JVM 方法 cinit())
3. 父类的实例构造,实例变量初始化 (实例变量初始实际会放到 JVM 的 init() 中)
4. 子类的实例构造,实例变量初始化 (也是对应的 init() 方法)

至于为什么最后才打印z?
因为子类的实例构造在子类的成员变量初始化之后,所以先初始化成员变量 Y y=new Y();
子类的构造实例在最后,所以最后才打印z
作者: 王峰    时间: 2012-8-17 17:07
//请楼主看我的注释
class X1
{
X1()
{
  System.out.println("x1");
}
}
class X2
{
X2()
{
  System.out.println("x2");
}
}
class Y extends X1
{
Y()
{
  System.out.println("y");
}
}
class Z extends X2
{
Z()
{
  System.out.println("z");
}
  Y y=new Y();
  }
class  Demo1
{
public static void main(String[] args)
{
  new Z();  //(1)首先创建Z实例,但是创建Z实例时首先加载父类X2,调用X2的构造方法;
                          //所以首先输出x2,加载类X2结束后,在加载Z,这时遇到new Y(),
                  //所以在加载类Y,发现类Y有父类,所以同时加载父类X1,等加载完毕
          //执行父类X1的构造方法,所以输出x1;然后在加载完毕类Y,执行类Y构造方法
  //所以输出y,然后在加载完成类Z,再执行类Z的构造方法,所以输出z
  
  //总之:楼主记住,当一个类有父类时,先加载父类;
          //等一个类加载完毕后再执行构造方法;当然如果加载类是由new或者语句块,首先执行这些
}
}
作者: 贾林栋    时间: 2012-8-18 10:29
金龙 发表于 2012-8-17 14:55
class X1
{
        X1()

现在明白了,谢谢!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2