黑马程序员技术交流社区

标题: 大神,关于继承,求救啊! [打印本页]

作者: liu951753xz    时间: 2014-10-11 23:13
标题: 大神,关于继承,求救啊!
    大神们,求看逻辑啊,这个函数是怎么调用的逻辑和内存分配,并赋值的先后顺序,我是新人,真的被其解说搞晕乎了
求给一个稍微简单易懂的分析和点拨!
  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?)代码附下:


作者: javaAndroid    时间: 2014-10-12 00:51
看一下对象的建立过程
建立对象的过程
        ► 先找到类文件,加载到内存中。
        ► 执行类中的static代码块(如果有的话),对类进行初始化。
        ► 在堆内存开辟空间,分配内存地址。
        ► 在堆内存建立对象的特有属性,并进行默认初始化。
        ► 对属性进行显示初始化。
        ► 对对象进行构造代码块初始化。
        ► 对对象进行构造函数初始化。
        ► 将内存地址赋给内存中的对象。
现在再来看你的子类,也就是Son类
在父类中你把i设置为private,所以子类Son继承不到i。
子类构造函数中有个隐式的super()
也就是你在new Son()的时候,实际是在堆内存上有了i,并且初值为0,有了fun()
然后在执行son构造函数的时候先去执行一下父类的无参构造函数,
在父类构造函数输出Son类的i的值,也就是0了。
执行完父类的构造函数,然后再继续给i赋值,也就是i=6这句。
这就是为什么输出的结果是0的原因。
个人的理解。不知道严不严谨。
作者: 郭.威    时间: 2014-10-12 01:56
这题你好好看完视频应该就没问题了,加油
作者: Quasimodo    时间: 2014-10-12 03:43
  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. }
复制代码


里面很多都是我自己猜的,也不知道对不对,中间还有个问题想不明白。
作者: liu951753xz    时间: 2014-10-12 20:46
javaAndroid 发表于 2014-10-12 00:51
看一下对象的建立过程
建立对象的过程
        ► 先找到类文件,加载到内存中。

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

谢谢,你的这个过程挺详细的
作者: Quasimodo    时间: 2014-10-12 21:00
liu951753xz 发表于 2014-10-12 20:47
谢谢,你的这个过程挺详细的

里面还是有错误的,就是到13步的时候,其实super()已经在前面执行完了,所以应该到14了的
作者: 2406035442    时间: 2014-10-12 21:17
游水。。

作者: yl82846094    时间: 2014-10-12 21:46
看看!!!
作者: qq8921310    时间: 2014-10-13 10:02
因为还没有读到赋值 就直接把 i给输出了、对吧。
作者: 浅木头    时间: 2014-10-13 12:21
mark一下
作者: Nullifier    时间: 2014-10-13 15:58
终于闹出个貌似合理的解释
  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楼主看这个就知道了,另外说下子类继承父类的时候私有的类成员变量也可以继承,但是不能访问,要想访问必须调用父类的共有方法




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