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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© liu951753xz 中级黑马   /  2014-10-11 23:13  /  1556 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

    大神们,求看逻辑啊,这个函数是怎么调用的逻辑和内存分配,并赋值的先后顺序,我是新人,真的被其解说搞晕乎了
求给一个稍微简单易懂的分析和点拨!
  1. class Father
  2. {
  3.         private int i = 2 ;
  4.         public Father()
  5.         {
  6.                 this.fun();//this代表正在初始化的java对象
  7.         }
  8.         public void fun()
  9.         {
  10.                 System.out.println(i);
  11.         }
  12. }

  13. class Son extends Father
  14. {
  15.         private int i = 4;
  16.         public Son()
  17.         {
  18.                 i = 6;        //②
  19.         }
  20.         public void fun()
  21.         {
  22.                 System.out.println(i);
  23.         }
  24. }

  25. class ExtendsTest
  26. {
  27.         public static void main(String[] args)
  28.         {
  29.                 new Son();//①       结果是 0 ,为什么?
  30.         }
  31. }
复制代码

!谢谢~~(怎么是0?)代码附下:

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1

查看全部评分

11 个回复

倒序浏览
看一下对象的建立过程
建立对象的过程
        ► 先找到类文件,加载到内存中。
        ► 执行类中的static代码块(如果有的话),对类进行初始化。
        ► 在堆内存开辟空间,分配内存地址。
        ► 在堆内存建立对象的特有属性,并进行默认初始化。
        ► 对属性进行显示初始化。
        ► 对对象进行构造代码块初始化。
        ► 对对象进行构造函数初始化。
        ► 将内存地址赋给内存中的对象。
现在再来看你的子类,也就是Son类
在父类中你把i设置为private,所以子类Son继承不到i。
子类构造函数中有个隐式的super()
也就是你在new Son()的时候,实际是在堆内存上有了i,并且初值为0,有了fun()
然后在执行son构造函数的时候先去执行一下父类的无参构造函数,
在父类构造函数输出Son类的i的值,也就是0了。
执行完父类的构造函数,然后再继续给i赋值,也就是i=6这句。
这就是为什么输出的结果是0的原因。
个人的理解。不知道严不严谨。

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1 很详细

查看全部评分

回复 使用道具 举报
这题你好好看完视频应该就没问题了,加油
回复 使用道具 举报 1 0
  1. class Father
  2. {
  3.         private int i = 2 ;    //4.这就是父类中的普通成员,此时i=2(显示初始化)。
  4.                  
  5.                 {
  6.                          System.out.println("1.父类中代码块...i="+i);  //5.为了验证上一步,我们在这里加个代码块。i应该=2
  7.                 }

  8.         public Father()       //6.接着执行父类的构造方法,也就是这里
  9.         {
  10.                 this.fun();   //7.里面有个this,指的是对象,也就是Son.
  11.                                  System.out.println("3.父类构造函数...i="+i);//9.再回到这一条语句。执行结束后该轮到子类的普通成员和代码块了i应该=2
  12.                 }

  13.         public void fun()
  14.         {
  15.                 System.out.println(i);
  16.         }
  17. }

  18. class Son extends Father      
  19. {               
  20.                
  21.                 private int i = 4;            //10.跳这里来,开始初始化子类中的成员变量和构造代码块。这里i=4了(显示初始化)         
  22.            {
  23.                System.out.println("4.子类构造代码块...i="+i);//11.这条是用来验证上一个说法的,i应该=4
  24.                   
  25.           
  26.            }
  27.         public Son()        //12.最后面才执行到这哥们..太悲催了
  28.         {
  29.                         super();   //13.  按理说应该轮到这哥们吧,可是竟然不是。想了半天不知道为什么。请各位大神说下,谢谢!
  30.             i = 6;
  31.                         System.out.println("5子类构造方法...i="+i);//14.最后应该是执行这个.i应该=6
  32.         }
  33.         public  void fun()                  
  34.         {
  35.                 System.out.println("2.子类fun方法...i="+i); //8.接着到fun()方法。i会在本类中查找,当然这里肯定就是i=0了。执行完了再跳回去
  36.                                
  37.         }
  38. }

  39. class ExtendsTest
  40. {
  41.         public static void main(String[] args)
  42.         {
  43.                 Son s = new Son();     //1.new一个子类对象。
  44.                                                                                 /*
  45.                                                                                    2.首先马上要初始化父类中的静态成员和代码块,然后是初始化子类中的静态成员和代码块。
  46.                                                                                      这个程序都没有。但是因为加载了两个类,所以应该先建立了子父类中的特有属性。并默认初始化
  47.                                                                                          父类中的i加了私有,所以子类要自己建立一个i。两个i都初始化变成0.
  48.                                                                                 */
  49.                                                                                 //3.紧接着要初始化父类的普通成员变量和代码块,再执行父类的构造方法;
  50.                                                                                
  51.                 }
  52. }
复制代码


里面很多都是我自己猜的,也不知道对不对,中间还有个问题想不明白。

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1 赞一个!

查看全部评分

回复 使用道具 举报
javaAndroid 发表于 2014-10-12 00:51
看一下对象的建立过程
建立对象的过程
        ► 先找到类文件,加载到内存中。

谢谢,你这个解释和老师的一样,其实我也觉得这题就是对象建立的过程的理解
回复 使用道具 举报
Quasimodo 发表于 2014-10-12 03:43
里面很多都是我自己猜的,也不知道对不对,中间还有个问题想不明白。

谢谢,你的这个过程挺详细的
回复 使用道具 举报
liu951753xz 发表于 2014-10-12 20:47
谢谢,你的这个过程挺详细的

里面还是有错误的,就是到13步的时候,其实super()已经在前面执行完了,所以应该到14了的
回复 使用道具 举报
游水。。
回复 使用道具 举报
yl82846094 来自手机 中级黑马 2014-10-12 21:46:50
9#
看看!!!
回复 使用道具 举报
因为还没有读到赋值 就直接把 i给输出了、对吧。
回复 使用道具 举报
mark一下
回复 使用道具 举报
终于闹出个貌似合理的解释
  1. package mytest;
  2. class Father
  3. {
  4.         private int i = 2 ;
  5.         public Father()
  6.         {
  7.             System.out.println("小白");   
  8.                 this.fun();//this代表正在初始化的java对象
  9.         }
  10.         public void fun()
  11.         {
  12.                 System.out.println("小明"+i);
  13.         }
  14. }

  15. class Son extends Father
  16. {
  17.         private int a=6 ;//这初始化的时候虚拟机服了个0 并没有把 6附近去。
  18.         public Son()
  19.         {       
  20.                
  21.                 //这里子类初始化的时候调用父类的构造函数中的东西所以这隐式的有 System.out.println("小白");   
  22.                 //this.fun();这两句,但是你下边有个fun()方法,他就认为你复写了父类的fun()方法,那么他就
  23.                 //读子类的fun()方法了。但是这是a只是定义并赋了个默认值,所以是零。个人理解只有当对象存在的时候
  24.                 //Java虚拟机才给变量赋值。所以这就调打了个   小红 0 ,也就是楼主看到的 0
  25.              a = 6;        //②
  26.             
  27.         }
  28.         
  29.         public void fun()//这里如果不跟父类一样的名字 那么在子类初试话的时候就调用父类的fun()方法了
  30.         {
  31.                 System.out.println(" 小红"+a);
  32.         }
  33. }

  34. class Son111
  35. {
  36.         public static void main(String[] args)
  37.         {
  38.                 //new Son();//①       结果是 0 ,为什么?
  39.                 new Son().fun();//打印结果 小白 小红0 小红6
  40.             
  41.         }
  42. }
复制代码

综上所述得出结论 类初始化的时候只是给类成员变量赋了个默认值,http://blog.csdn.net/fish3812/article/details/4434271楼主看这个就知道了,另外说下子类继承父类的时候私有的类成员变量也可以继承,但是不能访问,要想访问必须调用父类的共有方法
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马