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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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();
  }

}
(这段代码复制于http://bbs.itheima.com/forum.php ... mp;extra=#pid247419
该代码的输出结果是
zi show num = 0
cons code num = 8
cons function num = 8
这个结果说明,父类的构造函数是优先于,构造代码块执行的
但是我们学习视频的时候我记得,老师说过,子类的构造函数里
其实第一行默认调用父类无参的构造函数,也就是省略了super()
但是如果super()真的是被封装到子类构造函数中,那么应该是
先执行构造代码快,再执行父类构造函数,再执行自己本身的构造函数阿
所以子类构造函数第一行隐藏了 super()这段代码的说法是不是错误的?

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

14 个回复

倒序浏览
难道没有人知道??????
回复 使用道具 举报
我给子父类都加上了静态代码快和构造代码块。父类构造函数写成带参数的子类指定访问,我怕构造代码快前也有隐藏的super();  实验结果:第一是父类静态代码块。第二是子类静态代码块。第三父类构造代码块  .第四.父类构造函数(子类中指定访问的)第五.子类构造代码块。第六,子类构造函数。
我记得老师说过子类在建立对象时必须先访问父类的构造函数.看来对象初始化必须先走父类 走完父类才轮到子类。对象初始化父类整体优先于子类。
java的技术安全模式要求子类在执行任何东西之前,描述父类一个对象的各个方面都必须初始化。即初始化子类必先初始化父类。这是句从一个教材上抄的原话
子类构造代码快运行时已经开始初始化子类了,那么父类初始化应该在这之前执行完。
希望对你有所帮助

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 niexiaolu 于 2013-3-9 19:36 编辑

由于zi类继承了fu类,所以在实例化子类的时候就要先在内存中实例化父类的对象,并执行fu类的无参构造函数,这就很清楚了!其实这就是一个执行顺序的问题。对象一建立就会执行与之对应的构造函数,所以就执行了子类的构造函数,由于继承,故执行子类的super();语句!
回复 使用道具 举报
静态代码块:给类初始化的
构造代码块:给对象初始化的
构造函数:给对应对象初始化的
回复 使用道具 举报
王军行 发表于 2013-3-9 19:20
我给子父类都加上了静态代码快和构造代码块。父类构造函数写成带参数的子类指定访问,我怕构造代码快前也有 ...

我知道要先执行父类的初始化,问题是在哪一个时候
Person p = new Person();
这个代码其实在机器里一共走了8个步骤(教学视频里有详细介绍)
第7步骤是构造函数初始化,那肯定是在第7步之前,
那具体是在哪一步之前,哪一步之后
回复 使用道具 举报
只要在程序创建java对象时,系统总是先调用最顶层的父类的初始化动作,
包括初始化块和构造器,然后依次向下调用所有父类的初始化操作,
最终执行本类的初始化操作返回本类的实例.
--以上摘自疯狂java
回复 使用道具 举报
本帖最后由 门文通 于 2013-3-9 20:23 编辑

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

如果有错误   欢迎指正
回复 使用道具 举报
韩松范 发表于 2013-3-9 19:43
我知道要先执行父类的初始化,问题是在哪一个时候
Person p = new Person();
这个代码其实在机器里一共走 ...

我看来加载顺序是:
1主函数进栈 2.父类进栈(执行静态代码块初始化类)3.子类进栈 4.父类初始化(按照先构造代码块再构造函数顺序)5.子类初始化还是按照先构造代码块再构造函数顺序到这就完成了子类对象初始化,这个顺序只说明了方法的加载顺序不包括成员变量,成员变量初始化在什么时候进行呢?我定义了一个成员变量在各个部分引用验证了一下:父类静态变量和父类静态代码看哪个写在前面先加载哪个。然后再子类静态部分看语句顺序
之后:非静态父类成员变量和父类构造代码块看哪个写在前面,但是在父类构造函数之前加载
最后子类 成员变量和构造代码块看句子顺序 然后构造函数。
不知道能不能说明问题
回复 使用道具 举报
门文通 发表于 2013-3-9 20:21
对于对象实例化而言   毕老师的视频上只讲了  父类是Object类的对象实例过过程   
我总结了下  如果一个了 ...

要的就是这样的回答,哈哈
不过我感觉
6   执行父类构造函数
之前应该是子类对象开辟空间,并进行默认初始化
不然输出的结果zi show num = 0,这个0无法解释。
个人观点。。。。。
回复 使用道具 举报
韩松范 发表于 2013-3-9 21:14
要的就是这样的回答,哈哈
不过我感觉
6   执行父类构造函数

我写的就是这样啊    。。。。。。
回复 使用道具 举报
门文通 发表于 2013-3-10 04:23
我写的就是这样啊    。。。。。。

我说的是,6之前应该是,子类对象开辟空间,并进行默认初始化。。。
回复 使用道具 举报
韩松范 发表于 2013-3-10 13:00
我说的是,6之前应该是,子类对象开辟空间,并进行默认初始化。。。

5   在内存开辟空间   加载子父类的非静态变量  并默认初始化

我这句可能没说清楚  开辟空间 就是子类干的  然后加载进 非静态变量进来  默认初始化
回复 使用道具 举报
本帖最后由 贾振凯 于 2013-3-10 18:49 编辑

首先:我的实验代码如下:
public class SubClass {

      int num = 8;

    {
          num = 9;
         System.out.println("init block");
    }

    public SubClass(){
        // super();这里就是隐含调用哈,必须是在第一行
         num =10;
    }

}
在该类class文件所在路径通过    javap -c SubClass       对该类进行反编码得到的结果如下图:


你会发现代码会变成
public class SubClass {

     int num;

    public SubClass(){
          //super();这里就是隐含调用哈,必须是在第一行
          num = 8;                                   
          num = 9;
          System.out.println("init block");
          num =10;
    }
}
说到这你应该明白了吧!
其实构造块中的语句会被抽到构造函数中去执行,也就是说他们依然是在隐含调用父类构造函数之后才被执行!!!!!


评分

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

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马