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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 文密 中级黑马   /  2013-3-9 15:03  /  1633 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 文密 于 2013-3-10 20:52 编辑

class Fu{
   Fu(){
      show();
   }
  
   void show(){
        System.out.println("fu show run");
   }

}

class Zi extends Fu{

   int num = 8;
   {
       System.out.println("cons code num = " + num);
   }

   Zi(){
       System.out.println("cons function num = " + num);
   }

   void show(){

       System.out.println("zi show num = " + num);//此处为什么是0
   }

}


class Student{

  public static void main(String[] args){
     Zi z = new Zi();
  }

}

红色的地方有点想不明白啊  为什么会是0????

评分

参与人数 1技术分 +1 收起 理由
猫腻 + 1

查看全部评分

8 个回复

倒序浏览
子类继承父类的时候,先运行父类构造函数;具体的说就是运行父类时就会先“调用”父类的构造函数。(这是必须的)
而你父类的构造函数调用了show方法 ,这个show方法是调用的子类的里面省略了this.

Fu(){
       this.show();
    }

所以这里并不是对象调用的show方法 而是父类调用的 和子类里构造函数数的指向是不同的num  所以num!=8
这里可以这样验证
class Fu{
    Fu(){
      System.out.println("打印我");
    }
发现会先打印出    打印我

如果想让他输出8 必须对象调用show方法

public static void main(String[] args){
      Zi z = new Zi();
      z.show();
   }


所以严格说这句压根就没打印
void show(){

       System.out.println("zi show num = " + num);//此处为什么是0
    }

个人理解  希望能帮到你

评分

参与人数 1技术分 +1 收起 理由
高境 + 1 赞一个!

查看全部评分

回复 使用道具 举报
      程序运行前,fu类和zi类被加载到内存中,zi类继承fu类,对象创建时,fu类在内存中先被初始化,fu类的构造方法调用了fu的show方法,但是zi类又复写了fu类的show方法,
对象会调用子类的show方法完成初始化,此时,zi类的静态属性和初始化块还没有被人为初始化,所以输出的num值为系统默认初始化值,0.
      接着程序的执行顺序是:先为zi类的属性num指定值和执行初始化块,再执行zi类构造器里的代码。
运行结果的顺序如下:
zi show num = 0
cons code num = 8
cons function num = 8



  
回复 使用道具 举报
张文彬 发表于 2013-3-9 15:33
子类继承父类的时候,先运行父类构造函数;具体的说就是运行父类时就会先“调用”父类的构造函数。(这是必 ...

构造代码块不是:只要一创建对象,就优先于构造函数执行吗????????
回复 使用道具 举报
HM李超 发表于 2013-3-9 15:48
程序运行前,fu类和zi类被加载到内存中,zi类继承fu类,对象创建时,fu类在内存中先被初始化,fu类的 ...

zi类里面是没有静态属性,
构造代码块不是:只要一创建对象,就优先于构造函数执行吗????????
回复 使用道具 举报
本帖最后由 韩松范 于 2013-3-9 17:51 编辑

在new对象的时候,类加载器加载父类,和子类到内存中
在堆内存开辟空间,分配地址值,在堆内存中建立对象的特有属性,并进行默认出示化。
然后因该是调用父类的构造函数。以前我认为子类的构造函数里隐性了这个代码super(),现在对此我表示怀疑。。。。。。。。
结果说明,父类的构造函数是优先于构造代码块执行的,而构造代码块应该是优先于构造函数,
所以调用父类的方法应该不是隐性的封装在构造函数内部
调用父类的构造函数,发现构造函数调用了show()方法,而这个show()方法前面省略了this
子类调用的父类构造函数,所以this是子类,也就是说执行的是子类的show()方法,
那么此时,int num 还只是处在默认初始化的阶段,所以还是0,所以打印出来时是0

评分

参与人数 1技术分 +1 收起 理由
猫腻 + 1

查看全部评分

回复 使用道具 举报
文密 发表于 2013-3-9 17:40
构造代码块不是:只要一创建对象,就优先于构造函数执行吗???????? ...

是啊  但是  建立对象后直接看父类  可以理解为还没进子类那

可以在父类中加个构造代码块  就可以看出来了 谁先执行谁后执行

class Fu{
    Fu(){
      show();
    }
       
    {
       
        System.out.println("我先 " );
    }

   
    void show(){
         System.out.println("fu show run");
    }

}
回复 使用道具 举报
对于对象实例化而言   毕老师的视频上只讲了  父类是Object类的对象实例过过程   
我总结了下  如果一个了类有父类 且父类里面有静态变量  静态代码块  构造代码块  构造函数  子类如何实例化
可能不全  但大致如此
1  new子类之后   先加载父类进内存  再加载子类进内存
2   加载父类的静态变量  静态代码块 静态方法  所有静态依据代码顺序执行  不是先加载变量 再加载静态代码块 不是
3   加载子类的静态  和2一样
4   执行父类构造代码块
5   在内存开辟空间   加载子父类的非静态变量  并默认初始化
6   执行父类构造函数
7   给变量显示初始化。
8   执行子类构造代码块
9   执行子类构造函数  
OK   到这  基本就OK了

如果有错误   欢迎指正

评分

参与人数 1技术分 +1 收起 理由
猫腻 + 1

查看全部评分

回复 使用道具 举报
文密 中级黑马 2013-3-10 20:55:43
9#
我想说一点的就是今天我问了老师,
老师也没有给出我合适的答案     
  
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马