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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 熊冠银 中级黑马   /  2013-3-11 20:37  /  3325 人查看  /  20 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 熊冠银 于 2013-3-12 16:24 编辑
  1. class x
  2. {
  3.       Y y=new Y();
  4.        X()
  5.         {
  6.             System.out.println("X");
  7.         }
  8. }
  9. class Y
  10. {
  11.       Y()
  12.        {
  13.             System.out.prinltn("Y");
  14.        }
  15. }
  16. public class Z extends X
  17. {
  18.      Y y=new Y();
  19.      Z()
  20.      {
  21.          System.out.println("Z");
  22.      }
  23.     public static void main(String args[])
  24.     {
  25.         new Z();
  26.     }
  27. }
复制代码
打印的结果为什么会是"YXYZ"?
new Z()会调用Z的构造方法,第一行默认super语句指向了其父类的构造方法,所以先执行"x"在执行"Z".这个过程是怎么涉及到的Y的构造函数的?

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

20 个回复

倒序浏览
本帖最后由 袁见 于 2013-3-11 21:46 编辑
  1. public class Z extends X {
  2.         Y y = new Y();//第三步

  3.         Z() {
  4.                 System.out.println("Z");//第四步
  5.         }
  6.         public static void main(String args[]) {
  7.                 new Z();
  8.         }

  9. }

  10. class X {
  11.         Y y = new Y();//第一步

  12.         X() {
  13.                 System.out.println("X");//第二步
  14.         }
  15. }

  16. class Y {
  17.         Y() {
  18.                 System.out.println("Y");
  19.         }
  20. }
复制代码
解释:在main方法中创建Z类的实例,首先调用父类的构造函数,创建父类对象,
构造函数是创建对象的途径,在执行构造函数体之前先初始化对象的成员变量。
所以在创建父类对象的时,先执行父类对象的成员变量Y y = new Y();然后在执行构造体,执行完父类的构造体后,
执行Z类对象的成员变量,然后在执行Z类中的构造函数体。
所以打印的结果是YXYZ

希望对你有所帮助,继续加油

评分

参与人数 2技术分 +1 黑马币 +15 收起 理由
樊玲 + 15 很清楚。。
贾文泽 + 1 赞一个!

查看全部评分

回复 使用道具 举报
第一个类的类名X写成小写了  望大家改一下在运行
回复 使用道具 举报
class X

{          Y y=new Y();
         X()

        {System.out.println("X");

        }

}

class Y

{        Y()
       {

            System.out.println("Y");

       }

}

public class Z extends X

{         Y y=new Y();

     Z()

     {//super

      System.out.println("Z");

     }

    public static void main(String args[])

    {

        new Z();//"Y X YZ"?

    }
}
我的理解:new Z();执行z的构造代码块,z 里有new Y();对象,又去执行Y的代码块,打印Y,z的构造函数的super执行父类的代码块,打印X,X里又new Y(),打印Y,最后的打印Z。

评分

参与人数 1黑马币 +9 收起 理由
贾文泽 + 9

查看全部评分

回复 使用道具 举报
黑马17期-闫东东 发表于 2013-3-11 21:18
class X

{          Y y=new Y();

照你这么说,打印结果应该是y,y,x,z啊
回复 使用道具 举报
本帖最后由 小马过河 于 2013-3-12 08:57 编辑

我的理解是这样的, new Z();  1,先去加载其父类 class X ,  这其中就加载了class X 的成员  y ,调用了class Y的构造函数   打印Y
                                                2,然后是class X的构造函数的覆盖,打印X
                                                3,接着就到了class Z 了, 首先调用class Y 的构造函数,打印Y
                                                4,最后就是执行了 class Z的构造函数,打印Z
回复 使用道具 举报
class x
{
      Y y=new Y();//这里优先加载进内存中
       X()//这里是用来初始化X类的。
        {
           //这一行会有一个隐式的语句this()因为是父类,所以是执行本类构造函数
            System.out.println("X");
        }
}
class Y
{
      Y()
       {
            System.out.prinltn("Y");
       }
}
public class Z extends X
{
     Y y=new Y();
     Z()
     {
         System.out.println("Z");
     }
    public static void main(String args[])
    {
        new Z();//"Y X Y Z"
    }
}


以下是我个人理解。
以下步骤是在运行时的过程
第一步,先执行了主函数中的new Z();
第二步,也就是创建了Z对象之后,因为继承,也就是说先会执行X类中的语句,因为new Y() 的优先级高于构造函数初始化,所以就先new 了对象,也就是说先执行了Y类中         的构造函数 输出了“Y”
第三步,才是执行X中的构造函数 X(),也就是输出了“X”
第四步,这时候才回到Z类,执行 Y y = new Y();这一步,与第二步同理,输出了“Y”
第五步,这时候才会执行Z的构造函数。也就是给Z初始化 输出了Z
最终结果,
Y X Y Z
回复 使用道具 举报
本帖最后由 徐升2013 于 2013-3-11 22:29 编辑

首先你的代码书写错误有以下几点:
第一行 类名小写,而第4行构造函数的X是大写,
第13行 println写错了
因为x类名的原因,所以你的第16行也会报错。你自己修改下吧。

好了下面回答下你的问题吧:

原理怎么说呢, 类的构造方法是给对象初始化用的,而构造方法是可以在里面调用该类的参数的,也就是成员变量。这样说明白了么?
所以主方法先开始new Z,因为是继承类,所以一切先从父类加载,而父类加载的话 jvm默认会先加载成员进内存,好为了构造方法里面调用时备用,虽然构造方法可能未必调用该成员变量,但是虚拟机为了安全考虑还是会这么做。 所以加载一个对象new 了一个Y,而new Y就得调用 Y的构造方法, 所以打印输出了Y, 然后调用X的构造方法打印了X,然后Z类 加载自己的成员,然后打印Y,最后调用自己的构造方法打印了Z。


这里和静态的感觉有点类似我给你写个例子你就懂了:看下面代码:
class person
{
        String name ;
        person(String n)
        {
                name = n;
        }
}

public class Test
{
        public static void main(String argsp[])
        {
                person p =new person("张三");
        }
}

这个例子很简单了吧,你说我new 一个person对象的时候,是不是要往里面传参数?而构造方法是不是要调用他的一个成员变量name,而如果构造方法先存在,而成员变量后存在的话,这里是不是就会报错啊!因为构造方法先存在的话,虚拟机就会找不到name变量,所以是先加载成员变量,然后在加载构造方法,是这个样子的 这样你能明白点了么?还不明白就继续往后看先别纠结在这里。

回复 使用道具 举报
熊冠银 发表于 2013-3-11 20:39
第一个类的类名X写成小写了  望大家改一下在运行

这一点我也没搞懂,请教高手吧,我明天找人问下,再来解释吧,:handshake
回复 使用道具 举报
徐升2013 发表于 2013-3-11 22:11
首先你的代码书写错误有以下几点:
第一行 类名小写,而第4行构造函数的X是大写,
第13行 println写错了

给的答案感觉不科学
回复 使用道具 举报
袁见 发表于 2013-3-11 21:43
解释:在main方法中创建Z类的实例,首先调用父类的构造函数,创建父类对象,
构造函数是创建对象的途径,在 ...

“执行构造函数体之前先初始化对象的成员变量”,虽然第一次听这句话,但感觉很有理的样子
回复 使用道具 举报
好吧 我的书写错误,你们别纠结了,自己看到了,偷偷的改一下好了
回复 使用道具 举报
陈宇鹏 发表于 2013-3-11 22:08
class x
{
      Y y=new Y();//这里优先加载进内存中

“new Y()的优先级高于构造函数初始化,所以就先new了对象”有科学依据不,不要误导我啊
回复 使用道具 举报
“执行构造函数体之前先初始化对象的成员变量”,
回复 使用道具 举报
熊冠银 发表于 2013-3-11 22:22
“执行构造函数体之前先初始化对象的成员变量”,虽然第一次听这句话,但感觉很有理的样子 ...

执行构造函数之前是优先加载对象成员变量的
因为类变量也属于变量。
所以同理,是优先加载类变量 也就是  Y y  = new y();
回复 使用道具 举报
熊冠银 发表于 2013-3-11 22:22
“执行构造函数体之前先初始化对象的成员变量”,虽然第一次听这句话,但感觉很有理的样子 ...

确实是这样的,如果你有疑问,可以通过javap -c  类名  解析该类的java代码,你就会发现其原理。
回复 使用道具 举报
重新编辑了一下这回你看看你能看懂不
回复 使用道具 举报
熊冠银 发表于 2013-3-11 22:24
“new Y()的优先级高于构造函数初始化,所以就先new了对象”有科学依据不,不要误导我啊 ...

在毕老师的第六天的视频的单利设计模式之前的那一个视频有一段是说运行时创建对象时的执行过程的,你可以去看一下,第一步就是 因为new用到了Y.class,所以先找到该文件并加载到内存中,一直到第七步才是对对象进行对应的构造函数初始化
回复 使用道具 举报
陈宇鹏 发表于 2013-3-11 22:31
在毕老师的第六天的视频的单利设计模式之前的那一个视频有一段是说运行时创建对象时的执行过程的,你可以 ...

好的 多谢
回复 使用道具 举报
袁见 发表于 2013-3-11 22:28
确实是这样的,如果你有疑问,可以通过javap -c  类名  解析该类的java代码,你就会发现其原理。
...

多谢了 大哥
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马