A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

贾林栋

初级黑马

  • 黑马币:7

  • 帖子:30

  • 精华:0

© 贾林栋 初级黑马   /  2012-8-17 13:43  /  2847 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 贾林栋 于 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?

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

6 个回复

倒序浏览
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
        }
}

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
类初始化时构造函数调用顺序
1、初始化对象的存储空间为零或null值;
2、调用父类构造函数;
3、按顺序分别调用类成员变量和实例成员变量的初始化表达式;
4、调用本身构造函数

点评

谢谢  发表于 2012-8-18 10:30

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
------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-18 10:30

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
1. 初始化分为为的初始化和实例的初始化
2. 每个类在 JVM 中都对应一个 Class 实例
3. 父类实例是作为子例的部分存在的 (Class 实例之间也存在父子关系)
4. 初始化实例之前要初始化类

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

至于为什么最后才打印z?
因为子类的实例构造在子类的成员变量初始化之后,所以先初始化成员变量 Y y=new Y();
子类的构造实例在最后,所以最后才打印z

点评

谢谢!:handshake  发表于 2012-8-18 10:31

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
//请楼主看我的注释
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:31

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
金龙 发表于 2012-8-17 14:55
class X1
{
        X1()

现在明白了,谢谢!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马