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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 自己玩 黑马帝   /  2012-7-2 22:54  /  2570 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 自己玩 于 2012-7-2 22:57 编辑

class X {
        Y b = new Y();
        X() {
                        System.out.print("X");
        }
}

class Y {
        Y() {
                        System.out.print("Y");
        }
}

public class Z extends X {
        Y y = new Y();
        Z() {
                        System.out.print("Z");
        }

        public static void main(String[] args) {
                        new Z();
        }
}
打印结果是YXYZ,不明白结果是怎样来的。继承和main方法的执行顺序具体是怎样的?

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

12 个回复

倒序浏览
本帖最后由 Forever。 于 2012-7-2 23:28 编辑

楼主帮你缕一缕:
首先new Z();因为X是Z的父类,所以这时候程序会去先载入X,然后发现X里有一个new Y();于是打印Y
其实一开始就是运行Z的构造函数只不过子类的构造函数一般都会先去调用父类的构造函数,所以才会有上面的情况。所以这时候就该调用父类的构造函数了,于是打印了X
这时候父类算是完成任务了,然后发现Z里有一个new Y();于是这时候有打印了Y
最后运行了Z的构造函数打印出Z

这只是我的一点观点,如果有哪里说得不对 请大家指正……

回复 使用道具 举报
本帖最后由 蒋映辉 于 2012-7-3 00:02 编辑

class X {
        Y b = new Y();  --------------------------------------2
        X() {
                        System.out.print("X");  -----------------------4
        }
}

class Y {
        Y() {
                        System.out.print("Y");  ---------------------------------3
        }
}

public class Z extends X {
        Y y = new Y();   -----------------------------------------5
        Z() {
                        System.out.print("Z");---------------------6
        }

        public static void main(String[] args) {   
                        new Z();  ------------------------------1 执行它的时候发现它继承了x  所以先执行x
        }
}
回复 使用道具 举报

class X {
        Y b = new Y();//创建Y对象,调用Y的构造函数,打印Y
        X() {
                        System.out.print("X");
        }
}

class Y {
        Y() {
                        System.out.print("Y");
        }
}

public class Z extends X {//Z继承X,在Z的第一行隐藏了super();而该方法会自动调用父类函数中的构造方法,而X中先调用了Y的构造方法,再调用自己的构造方法,因此创建Z对象后,在执行Y y = new Y()之前就打印出YX        
Y y = new Y();//在调用Z的构造方法之前,先创建Y类的对象,先调用构造函数Y(),打印出Y
        Z() {
                        System.out.print("Z");
        }

        public static void main(String[] args) {
                        new Z();、、//创建Z对象时先调用父类中的构造方法,打印出YX,紧接着调用到Z中的构造方法打印出YZ
        }
}

点评

此楼正解 跟我想的一样 不过我貌似写的太繁琐了写呵呵  发表于 2012-7-2 23:42

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
class X {
                //在 x类中 实例化y 对象。
        Y b = new Y();
        X() {// x 类的 无参构造方法       默认执行
                        System.out.print("X");
        }
}

class Y {
        Y() {// y 类的 无参构造方法 默认执行
                        System.out.print("Y");
        }
}

public class Z extends X {// z类 继承 x 类  中的 方法 属性。
        Y y = new Y();//实例化 y 对象   在调用Z的构造方法之前,先创建Y类的对象,先调用构造函数Y(),打印出Y
        Z() {// z 类的 无参构造方法   默认执行
                        System.out.print("Z");
        }

       public static void main(String[] args) {
                        new Z();//创建Z对象时先调用父类中的构造方法,打印出YX,紧接着调用到Z中的构造方法打印出YZ
        }
}
回复 使用道具 举报
class X
{
        Y b = new Y();//3.执行该语句,加载类Y,输出Y
        X()
                {
            System.out.print("X");//4.执行父类构造函数,输出X
        }
}

class Y
{
       Y()
          {
             System.out.print("Y");
       }
}

public class Z extends X
{
        Y y = new Y();//5.加载完父类构造函数,开始执行子类中的语句.此语句又加载类Y,打印Y
        Z()
                {
              System.out.print("Z");//6.最后执行子类构造函数,打印Z
        }

        public static void main(String[] args)//1.程序入口:main函数
                {
                        new Z();//2.new一个Z类的对象,发现函数继承类X,加载X类
                }
}
不知道是不是这么个执行顺序,请大神指点!!!!
回复 使用道具 举报
class X {
    Y b = new Y();
    X() {
        System.out.println("X");
    }
}

class Y {
        Y() {
                System.out.println("Y");
        }
}

public class Z extends X {
        Y y = new Y();
    Z() {
        System.out.println("Z");
    }

    public static void main(String[] args) {
                new Z();//1、创建z对象时,先调用父类X中的构造方法,先执行类X中的Y y=newY();打印出Y,再打印出X
                                              //2、紧接着执行Z中的构造方法,先执行Z中的Y y = new Y(),打印出Y,在打印Z。所以打印出来的顺心就是YXYZ
    }
}
回复 使用道具 举报
蒋映辉 发表于 2012-7-2 23:14
class X {
        Y b = new Y();----------------------------------------------4 执行它 并输出它的构 ...

版主我的想法和推断的执行顺序跟你貌似完全相反,main函数不是程序入口么?为什么先执行Z类的Y y=new Y()?
我刚学没多久....懂得不多,所以烦请版主帮忙解惑下.我怕下次碰到类似的还是不懂....嘻嘻...谢谢哈
回复 使用道具 举报
我把楼主的改了一下,可以看顺序
  1. class X {
  2. Y b = new Y(3);
  3. X() {
  4. System.out.print("X");
  5. }
  6. }

  7. class Y {
  8. Y()
  9. {
  10. System.out.print("y");
  11. }
  12. Y(int x)
  13. {
  14. System.out.print(x);
  15. }
  16. }

  17. public class Z extends X {
  18. Y y = new Y();
  19. Z() {
  20. System.out.print("Z");
  21. }

  22. public static void main(String[] args) {
  23. new Z();
  24. }
  25. }
复制代码
结果为

结果证明程序用main函数入口开始,当new一个子类对象时要先访问父类的构造函数,因为父类中有显式初始化,所以初始化先于构造函数执行,所以先new 一个带参的Y类对象,打印3,然后是父类的构造函数打印X,然后到子类的构造函数,同理要先执行初始化,new 一个无参的构造函数,打印y,最后是子类的构造函数,打印Z。所以成员变量的初始化优先于构造函数执行,顺便说一下,如果有静态代码块优先于构造代码块优先于构造函数,题外话啊,呵呵

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1 很给力! 恩 你是对的

查看全部评分

回复 使用道具 举报
本帖最后由 蒋映辉 于 2012-7-2 23:55 编辑
夏儒日 发表于 2012-7-2 23:47
版主我的想法和推断的执行顺序跟你貌似完全相反,main函数不是程序入口么?为什么先执行Z类的Y y=new Y()?
...


看九楼的方法吧  他的是对的 我的错了
回复 使用道具 举报
蒋映辉 发表于 2012-7-2 23:49
因为它要建立了对象 有了这些资源以后  main函数才能正常执行啊  所以都要先把该初始化的初始化了  该建 ...

了解了,谢谢版主哈!!!感觉我们初学者很多问题看得比较模糊..所以很多细节比较难滤清.....多谢版主哈~~~:handshake
回复 使用道具 举报
class X {
        Y b = new Y();//1.首先会进来这里,为什么,因为z继承了X在调用自己的构造函数的时候会先调用父类的 然后会调用Y的构造函数打印出Y

        X() {
                System.out.println("X");//2.进来这里讲x打印出来
                System.out.println(this.getClass().getName());//这里给你添了两段代码帮助你理解 为什么返回来的都是Z呢,因为getClass返回的是运行时的类
                                                                                                                //你现在运行的类是Z是通过执行Z来调用的父类的构造方法,所以返回的是运行的Z 下面的代码返回的也是
                                                                                                                //因为getClass是Object继承过来的 但是只继承未重写,该类的定义就是返回运行时的类的字节码,所以this和super的效果是一样的
                System.out.println(super.getClass().getName());
        }
}

class Y {
        Y() {
                System.out.println("Y");
                System.out.println(this.getClass().getName());
                System.out.println(super.getClass().getName());
               
        }
}

public class Z extends X {
        Y y = new Y();//3接下来会来这里先初始化变量 因为我们都知道  对象创建的时候就已经默认初始化了,对象的默认值是null基本类型是0,这里是组合类,所以会先初始化成员变量
                             //所以会再次打印出Y

        Z() {
                System.out.print("Z");//最后回来打印出Z
        }

        public static void main(String[] args) {
                new Z();
        }
}
回复 使用道具 举报
匿名对象:new Z();
1  先调用父类的方法,执行父类的语句
2 接执行子类的语句


未命名.JPG (38.18 KB, 下载次数: 31)

未命名.JPG

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马