前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【面试题】Java中子类和父类静态代码块、非静态代码块、构造函数的执行顺序总结一览表

【面试题】Java中子类和父类静态代码块、非静态代码块、构造函数的执行顺序总结一览表

原创
作者头像
凯哥Java
发布2022-12-02 10:12:11
5280
发布2022-12-02 10:12:11
举报
文章被收录于专栏:凯哥Java凯哥Java凯哥Java

在面试的时候,有时候我们会被问到这样的问题:子类A继承父类B,A a = new A();则父类B的构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块执行的先后顺序是什么?

60385df33e1170e6848cd451dd6e8bc5.png
60385df33e1170e6848cd451dd6e8bc5.png

我们先根据上面的题目,可以写出如下代码:

父类B代码如下:

public class B {     public B(){         System.out.println("父类B的构造函数");     }     static {         System.out.println("父类B的中的静态代码块");     }     {         System.out.println("父类B的中的非静态代码块 sya()");     } }

子类A代码如下:

public class A extends B{     public A(){         System.out.println("子类A的构造函数");     }     static {         System.out.println("子类A的中的静态代码块");     }     {         System.out.println("子类A的中的非静态代码块 sya()1");     }     public static void main(String[] args) {         A a = new A();         System.out.println("A!");         A a2 = new A();         System.out.println("启动完成");     } }

请问控制台打印的顺序是什么?

在回答这个问题前,我们要抓住几个关键的点:

①:静态代码块;②:非静态代码块;③构造函数;④:父类与子类;⑤:类的加载、初始化及实例化

上面这几个就是本题的考点,我们要弄清楚每个考点在类的生命周期中执行的时机。我们来分开介绍:

先来说说的类生命周期:

31482d9dcbc3e016c04a4f2b7d1073ea.png
31482d9dcbc3e016c04a4f2b7d1073ea.png

此图来源于凯哥之前写的文章。

一:静态代码块

静态代码块是被static修饰的代码块。被static修饰的代码块,是属于当前类的信息,是用来初始化类的信息。我们知道类加载过程是先将编译后的class文件加载到内存中,一个类只会被加载到内存中一次。而static修饰的代码块属于类的信息的,所以,静态代码块中的代码有且只有一次被执行。执行的时机:类被加载的时候。

二:非静态代码块

非静态代码块是用来初始化类实例信息的。当我们new关键字创建一个对象的时候,就会被执行,而且每使用一个new关键字创建出一个新对象的时候就会被执行一次的。非静态代码块也可以叫作:非静态初始化代码块的运行时机:会在构造函数执行时候,在构造函数代码执行之前被运行的

三:构造函数

构造函数或者构造方法不用多说了吧,就是用来创建对象的。

我们来看下父类B编译成class文件的时候,非静态代码块和构造函数相关的代码如下:

12695413cb14c01596fbdb204c1c7cc3.png
12695413cb14c01596fbdb204c1c7cc3.png

从代码中,我们可以看出非静态代码块的执行顺序优先于构造函数的。

四:父类与子类

父类与子类的加载时机:父类在子类前面

需要注意的是:子类的构造方法,不管是无参构造还是有参构造,默认都会先去寻找父类的无参构造方法。如果父类中,没有无参构造,那么子类必须使用supper这个关键字来调用父类带参数的构造方法,否则在编译期都不能通过。如下图:

bd53cca7034b23f22506d8da1d500e6a.png
bd53cca7034b23f22506d8da1d500e6a.png

五:类的加载、初始化及实例化

类的加载、初始化及实例化过程,还有类在运行的时候,变量在JVM中怎么分布的,凯哥之前也写过文章详细介绍了。如果想了解更多,可以看看这几篇文章《JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇》、《JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇》和《一个Java类在运行时候,变量是怎么在JVM中分布的呢?》

9b3e0253e18133cb3618de26a9be7a1d.png
9b3e0253e18133cb3618de26a9be7a1d.png

总结:

好了,通过上面分析,我们可以得到以下总结:

1:如果在同一个类中静态代码块、非静态代码块、构造函数的执行顺序如下:

静态代码块→非静态代码块→构造函数

这个过程,我们反编译class文件也可以看到。如下图:

3c76b47413cad3cd004ba09dce21e71a.png
3c76b47413cad3cd004ba09dce21e71a.png

2:父类和子类中静态代码块、非静态代码块、构造函数的执行顺序:

父类中的静态代码块→子类中的静态代码块→父类非静态代码块→父类构造函数→子类非静态代码块→子类构造函数

具体加载如下图:

e0891aaf62a0b9980e1103d1ec4f18b9.png
e0891aaf62a0b9980e1103d1ec4f18b9.png

所以,根据上面的分析,我们可以知道运行的结果:

父类B的中的静态代码块 子类A的中的静态代码块 父类B的中的非静态代码块 sya() 父类B的构造函数 子类A的中的非静态代码块 sya()1 子类A的构造函数 A! 父类B的中的非静态代码块 sya() 父类B的构造函数 子类A的中的非静态代码块 sya()1 子类A的构造函数 启动完成

868eec064864ba93f5c5cf69f760bea2.png
868eec064864ba93f5c5cf69f760bea2.png

总之一句话总结:

父类早于子类、静态早于非静态、非静态早于构造函数

561cb0b61c43f7f10a4671a42ff76297.png
561cb0b61c43f7f10a4671a42ff76297.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:静态代码块
  • 二:非静态代码块
  • 三:构造函数
  • 四:父类与子类
  • 五:类的加载、初始化及实例化
  • 总结:
    • 1:如果在同一个类中静态代码块、非静态代码块、构造函数的执行顺序如下:
      • 2:父类和子类中静态代码块、非静态代码块、构造函数的执行顺序:
      • 总之一句话总结:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档