黑马程序员技术交流社区

标题: 构造方法和继承 [打印本页]

作者: 自己玩    时间: 2012-7-2 22:54
标题: 构造方法和继承
本帖最后由 自己玩 于 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方法的执行顺序具体是怎样的?
作者: Forever。    时间: 2012-7-2 23:09
本帖最后由 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-2 23:14
本帖最后由 蒋映辉 于 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
        }
}

作者: 黄丽慧    时间: 2012-7-2 23:18

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:27
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
        }
}

作者: 夏儒日    时间: 2012-7-2 23:42
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类
                }
}
不知道是不是这么个执行顺序,请大神指点!!!!
作者: 赵庆礼    时间: 2012-7-2 23:43
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:47
蒋映辉 发表于 2012-7-2 23:14
class X {
        Y b = new Y();----------------------------------------------4 执行它 并输出它的构 ...

版主我的想法和推断的执行顺序跟你貌似完全相反,main函数不是程序入口么?为什么先执行Z类的Y y=new Y()?
我刚学没多久....懂得不多,所以烦请版主帮忙解惑下.我怕下次碰到类似的还是不懂....嘻嘻...谢谢哈
作者: 孙飞    时间: 2012-7-2 23:48
我把楼主的改了一下,可以看顺序
  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。所以成员变量的初始化优先于构造函数执行,顺便说一下,如果有静态代码块优先于构造代码块优先于构造函数,题外话啊,呵呵

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


看九楼的方法吧  他的是对的 我的错了
作者: 夏儒日    时间: 2012-7-2 23:56
蒋映辉 发表于 2012-7-2 23:49
因为它要建立了对象 有了这些资源以后  main函数才能正常执行啊  所以都要先把该初始化的初始化了  该建 ...

了解了,谢谢版主哈!!!感觉我们初学者很多问题看得比较模糊..所以很多细节比较难滤清.....多谢版主哈~~~:handshake
作者: 周朋飞    时间: 2012-7-3 00:12
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();
        }
}

作者: 林康春    时间: 2012-7-3 00:56
匿名对象:new Z();
1  先调用父类的方法,执行父类的语句
2 接执行子类的语句


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

未命名.JPG





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