【黑马程序员济南中心】继承中的构造代码块执行顺序

2018-04-28  本文已影响0人  b06ee9db5ac0

相信有很多的同学都遇到了这样一道面试题目,题目是请问程序的执行结果,代码如下:

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");

        }

}

下面我们循序渐进的来研究一下这个题目,

首先我们先来讲讲什么是代码块

代码块就是用{}括起来的代码,根据代码块的功能、执行顺序和书写位置,我们把代码块分为  静态代码块,构造代码块,局部代码块。

静态代码块:书写在成员位置, 大括号前面有static关键字,仅随着类的加载执行一次,所以可以在里面一些项目中的初始化的内容。

构造代码块:书写在成员位置,每次创建对象的时候构造代码块都会执行一次,而且是在构造方法的内容执行之前执行,所以可以写一些该类里面所有构造方法共性的内容。

局部代码块:书写在局部位置(即方法里面),可以尽早的让变量在内存中消失,略微提升一些效率

接着 , 我们按照上面对代码块的理解去分析一下这道的面试题的答案

首先执行 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文件拖进反编译工具,你会发现反编译出来的代码和原来的代码有一些差异,代码如下:

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()语句下面的位置

上一篇下一篇

猜你喜欢

热点阅读