黑马程序员技术交流社区

标题: 【济南中心】继承中的构造代码块执行顺序详解 [打印本页]

作者: 大山哥哥    时间: 2016-10-6 19:40
标题: 【济南中心】继承中的构造代码块执行顺序详解
本帖最后由 小鲁哥哥 于 2020-1-8 18:56 编辑

                点击查看济南黑马校区最新开班计划                                 

  
在继承中的三种代码块的执行顺序详细解释                


在我们Android基础班第八天,相信所有的同学都遇到了这样一道面试题目,题目是请问程序的执行结果,代码如下:
[Java] 纯文本查看 复制代码
class Test2_Extends {
        public static void main(String[] args) {
                Zi z = new Zi();
        }
}
class Fu {
        static {
                System.out.println("静态代码块Fu");
        }
        {
                System.out.println("构造代码块Fu");
        }
        public Fu() {
                System.out.println("构造方法Fu");
        }
}
class Zi extends Fu {
        static {
                System.out.println("静态代码块Zi");
        }
        {
                System.out.println("构造代码块Zi");
        }
        public Zi() {
                System.out.println("构造方法Zi");
        }
}
下面我们循序渐进的来研究一下这个题目,
首先我们先来讲讲什么是代码块
代码块就是用{}括起来的代码,根据代码块的功能、执行顺序和书写位置,我们把代码块分为  静态代码块,构造代码块,局部代码块。
接着 , 我们按照上面对代码块的理解去分析一下这道的面试题的答案
首先执行 Zi z = new Zi();创建Zi类对象的时候,必须先加载Zi类的父类Fu,接着加载Zi类,那么Fu类和Zi类中的静态代码块就会随着类的加载而依次执行了,然后程序即将执行Zi类的构造方法,但是在构造方法执行之前必须先执行Zi类的构造代码块,接着执行Zi类的构造方法, 由于Zi类的构造方法第一行语句默认都有super(),所以接着将要去执行父类Fu的构造方法,但是在执行Fu的构造方法之前,先执行Fu的构造代码块,然后才能执行Fu的构造方法,执行Fu的这些内容后,才接着执行Zi类构造方法的后续内容。那照这样看来,执行结果应该是如下这样的
静态代码块Fu
静态代码块Zi
构造代码块Zi
构造代码块Fu
构造方法Fu
构造方法Zi

但是 , 事实并非如此,我们实际运行了一下 却发现执行结果是如下这样的:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi

这究竟是为什么呢?为什么和我们分析结果不一样呢?   这其实与构造代码块被编译到的位置有关。
接下来,我就利用反编译(反编译就是把class文件转成java文件)技术来解释一下这道面试题:首先介绍一个反编译工具"jd-gui.exe"(详见附件),打开反编译工具,将次此程序的class文件拖进反编译工具,你会发现反编译出来的代码和原来的代码有一些差异,代码如下
[Java] 纯文本查看 复制代码
class Test2_Extends
{
  public static void main(String[] paramArrayOfString)
  {
    Zi localZi = new Zi();
  }
}
class Fu
{
  public Fu()
  {
    System.out.println("构造代码块Fu");

    System.out.println("构造方法Fu");
  }

  static
  {
    System.out.println("静态代码块Fu");
  }
}
class Zi extends Fu
{
  public Zi()
  {
    System.out.println("构造代码块Zi");

    System.out.println("构造方法Zi");
  }

  static
  {
    System.out.println("静态代码块Zi");
  }
}
大家仔细查看反编译出来的代码 和原来的代码有什么区别呢
很明显,就是反编译出来的代码,构造代码块被写到了构造方法的最上面一行(别忘了这一行的上面还有super()呢),根据这个代码我们不难理解题目运行的结果
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi

其实讲到现在,我相信大家已经理解了上面的面试题,这道题最关键的理解点就是 构造代码块在编译期间其实是编译到了构造方法里面super()语句下面的位置


jd-gui-反编译工具.zip

690.29 KB, 下载次数: 199

java反编译工具


作者: 济南王昭珽    时间: 2016-10-6 21:34
不错,非常详细,收藏了
作者: yinyujue    时间: 2016-10-6 22:09
又来学习咯

作者: 一半的留言    时间: 2016-10-6 22:12
学习了            
作者: Zzh94520    时间: 2016-10-6 22:12
....................
作者: 橘子哥    时间: 2016-10-7 09:29
大神的教程贴,快来收藏啦!
作者: 愿望变美    时间: 2016-10-7 10:14
嗯嗯,收藏,
作者: 职业规划-王雪老师    时间: 2016-10-7 10:20
{:5_275:}
作者: jayfan1991    时间: 2016-10-7 12:43
good.非常给力吆,加油
作者: jayfan1991    时间: 2016-10-7 12:53
不错不错,非常的好的咱
作者: 9527个人    时间: 2016-10-7 13:07
居然有反编译工具..{:3_51:}
作者: 万物皆数    时间: 2016-10-7 15:13
看到很好就进来看看
作者: 周军福    时间: 2016-10-7 15:18
成功登陆系统
作者: 李杰老师    时间: 2016-10-7 15:57
赞一个,非常详细
作者: 寒冰夜    时间: 2016-10-7 18:21
谢谢分享...嘎嘎嘎
作者: 哦啊啊    时间: 2016-10-7 18:33
学习了 今天刚好学到这里
作者: 哈韩浪子    时间: 2016-10-7 19:04
非常好的啊资料
作者: HermitXU    时间: 2016-10-7 21:52
dddddddddd
作者: tliangl928    时间: 2016-10-7 22:29
爱黑马,爱生活……
作者: 祖国的园丁    时间: 2016-10-7 22:33
6666666666666
作者: xuezhangjun    时间: 2016-10-7 22:46
只要代码敲的好,老婆年年在高考.

作者: 黑马121    时间: 2016-10-7 22:58
黑马,你等着!我肯定要上了你!!!
作者: juanjuan    时间: 2016-10-7 23:23
终于弄懂了,感谢楼主.
作者: yanghaozhang    时间: 2016-10-7 23:31
只要代码敲得好,房子车子不用愁
作者: seedseed555    时间: 2016-10-7 23:39
6666666666666666666
作者: zhoubinjian    时间: 2016-10-7 23:45
来支持下
作者: zhuangshuang123    时间: 2016-10-7 23:55
支持橘子哥
作者: 刘毅ly    时间: 2016-10-8 00:06
支持橘子哥!!嘿嘿
作者: 其实我是黑马    时间: 2016-10-8 00:08
大山大哥是哪个讲师?

作者: 帅哥军    时间: 2016-10-8 01:05
明天点招 加油 加油!
作者: 周军福    时间: 2016-10-8 08:52
明天点招 加油 加油!

作者: wangkai426    时间: 2016-10-8 09:02
解释的很详细,值得收藏,赞
作者: oss1122    时间: 2016-10-8 09:15
感谢分享,收藏了~
作者: 哦啊啊    时间: 2016-10-8 12:38
又来顶上去~好资源
作者: 饭要大口吃    时间: 2016-10-8 14:43
很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.很好.
作者: xuezhangjun    时间: 2016-10-8 15:00
888888666666
作者: zhoubinjian    时间: 2016-10-8 16:51
来支持下。
作者: 杨杰锋    时间: 2016-10-8 18:26
学习了{:2_32:}
作者: Angel若梦    时间: 2016-10-8 19:38
其实我是黑马 发表于 2016-10-8 00:08
大山大哥是哪个讲师?

我们贤哥....
作者: tliangl928    时间: 2016-10-8 21:41
爱黑马,爱生活……
作者: wangyuit    时间: 2016-10-8 22:13
贤哥辛苦了,继续努力啊
作者: zhuangshuang123    时间: 2016-10-8 22:14
爱黑马爱生活
作者: bjwqcpy@126.com    时间: 2016-10-8 22:36
写的很详细,学习了!
作者: 渔夫的星辰    时间: 2016-10-8 22:55
学习一下
作者: Da_xigua    时间: 2016-10-8 23:03
哈哈  贤哥的帖子必须顶,学习啦
作者: Da_xigua    时间: 2016-10-8 23:05
哈哈  贤哥的帖子必须顶,学习啦
作者: 刘毅ly    时间: 2016-10-9 00:37
深夜需要鸡汤
作者: seedseed555    时间: 2016-10-9 02:30
6666666666666666666666
作者: skyleon    时间: 2016-10-9 09:22
感谢分享,学习了
作者: wangyuit    时间: 2016-10-9 11:49
66666666666666
作者: 792241113    时间: 2016-10-9 17:08
肯定先执行静态   因为静态是随着类的加载而加载   然后只执行一次的 ,, 之后就是 根据 继承的关系   子继承看父  必然现有父, 程序中没有父亲  这么造出儿子呢   构造代码块  等等都是正常加载的  按照正常的顺序   执行顺序:(优先级从高到低。)静态代码块>mian方法>构造代码块>构造方法。

其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。
作者: Hans_mile    时间: 2016-10-9 19:34
无奋斗,不青春。。。。。。。。。。。。。。。
作者: 周军福    时间: 2016-10-9 20:08
点招顺利结束
作者: tliangl928    时间: 2016-10-9 21:02
爱黑马,爱生活……
作者: 万物皆数    时间: 2016-10-9 21:15
战略mark
作者: juanjuan    时间: 2016-10-9 23:12
今天面试这个面试题也问了,感谢楼主....
作者: mafu1993    时间: 2016-10-9 23:57
明天上课 大家晚安
作者: mafu1993    时间: 2016-10-10 00:04
这题目,在网上视频讲过,当时已经理解了

作者: woxiangxuexi    时间: 2016-10-10 07:37
这个其实挺不错的,继续分享吧,
作者: songfei    时间: 2016-10-10 07:42
感谢分享,不错,非常详细
作者: songchangchang    时间: 2016-10-10 09:43
看来三种代码块很重要啊,自己练习一下:静态代码块随着类的加载而加载>>构造代码块>>构造方法,赞吧
作者: q哇哈哈qq    时间: 2016-10-10 10:18
原来如此,纠结了好久

作者: 老爹很帅    时间: 2016-10-10 16:44
谢谢分享,支持
作者: lolikaori    时间: 2016-10-10 22:17
很好.又学到了新知识
作者: 磊哥哥    时间: 2016-10-10 22:20
谢谢分享,支持
作者: 周军福    时间: 2016-10-10 22:51
很好.又学到了新知识
作者: MasksX    时间: 2016-10-10 23:13
谢谢分享!!
作者: 足球骑士szw    时间: 2016-10-10 23:21
哈哈,前一段时间还在为这个纠结
作者: 足球骑士szw    时间: 2016-10-10 23:22
6666666666666
作者: 松松    时间: 2016-10-10 23:25
赞赞赞赞赞赞
作者: zq0801    时间: 2016-10-10 23:30
厉害,谢谢题主的分析,很受用
作者: 李孝志    时间: 2016-10-10 23:46
学到了,谢谢分享
作者: ouyzm    时间: 2016-10-11 00:02
赞  一个这个确实必须知道的
作者: 轻语轻狂    时间: 2016-10-11 00:35
弄清楚程序执行时的加载顺序就OK了
作者: 轻语轻狂    时间: 2016-10-11 00:37
弄清楚程序执行时的加载顺序就OK了
作者: 1078866818    时间: 2016-10-11 01:02
重写tostring为什么呢/求大神指点,
作者: seedseed555    时间: 2016-10-11 01:10
666666666666666666666
作者: 13628611006    时间: 2016-10-11 08:25
子类在完成初始化前先完成对父类的初始化
作者: wanghui2821479    时间: 2016-10-11 18:35
阿斯达所大所多阿萨德阿萨德阿萨德爱上大叔的
作者: wanghui2821479    时间: 2016-10-11 18:36
谁给我点黑马比
作者: 磊哥哥    时间: 2016-10-11 22:49
签到,签到。
作者: 顺其自然吧    时间: 2016-10-11 23:04

为了黑马币!!!顶起!{:2_32:}
作者: 蓝光四号    时间: 2016-10-11 23:37
签到    1
作者: u8u8u80pp    时间: 2016-10-12 00:08
签到,签到。
作者: LXD2016    时间: 2016-10-12 00:09
很好很强大,66666666666666666666
作者: seedseed555    时间: 2016-10-12 01:59
666666666666666666666
作者: 黑马121    时间: 2016-10-12 11:16
6666666666666666666666666666666
作者: 苏小溪    时间: 2016-11-8 20:30
反编译,6666。。。

作者: wain    时间: 2016-11-8 22:43
贤哥威武!{:8_507:}
作者: 薄拉图图图    时间: 2016-11-8 23:17
日子还是得过   加油吧我
作者: szq121586    时间: 2016-11-8 23:35
可明白了
作者: wxm278187618    时间: 2016-11-14 00:55
感谢楼主分享




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