在面试的时候,有时候我们会被问到这样的问题:子类A继承父类B,A a = new A();则父类B的构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块执行的先后顺序是什么?
我们先根据上面的题目,可以写出如下代码:
父类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("启动完成"); } }
请问控制台打印的顺序是什么?
在回答这个问题前,我们要抓住几个关键的点:
①:静态代码块;②:非静态代码块;③构造函数;④:父类与子类;⑤:类的加载、初始化及实例化
上面这几个就是本题的考点,我们要弄清楚每个考点在类的生命周期中执行的时机。我们来分开介绍:
先来说说的类生命周期:
此图来源于凯哥之前写的文章。
一:静态代码块
静态代码块是被static修饰的代码块。被static修饰的代码块,是属于当前类的信息,是用来初始化类的信息。我们知道类加载过程是先将编译后的class文件加载到内存中,一个类只会被加载到内存中一次。而static修饰的代码块属于类的信息的,所以,静态代码块中的代码有且只有一次被执行。执行的时机:类被加载的时候。
二:非静态代码块
非静态代码块是用来初始化类实例信息的。当我们new关键字创建一个对象的时候,就会被执行,而且每使用一个new关键字创建出一个新对象的时候就会被执行一次的。非静态代码块也可以叫作:非静态初始化代码块的运行时机:会在构造函数执行时候,在构造函数代码执行之前被运行的
三:构造函数
构造函数或者构造方法不用多说了吧,就是用来创建对象的。
我们来看下父类B编译成class文件的时候,非静态代码块和构造函数相关的代码如下:
从代码中,我们可以看出非静态代码块的执行顺序优先于构造函数的。
四:父类与子类
父类与子类的加载时机:父类在子类前面
需要注意的是:子类的构造方法,不管是无参构造还是有参构造,默认都会先去寻找父类的无参构造方法。如果父类中,没有无参构造,那么子类必须使用supper这个关键字来调用父类带参数的构造方法,否则在编译期都不能通过。如下图:
五:类的加载、初始化及实例化
类的加载、初始化及实例化过程,还有类在运行的时候,变量在JVM中怎么分布的,凯哥之前也写过文章详细介绍了。如果想了解更多,可以看看这几篇文章《JVM学习第一篇思考:一个Java代码是怎么运行起来的-上篇》、《JVM学习第二篇思考:一个Java代码是怎么运行起来的-下篇》和《一个Java类在运行时候,变量是怎么在JVM中分布的呢?》
总结:
好了,通过上面分析,我们可以得到以下总结:
1:如果在同一个类中静态代码块、非静态代码块、构造函数的执行顺序如下:
静态代码块→非静态代码块→构造函数
这个过程,我们反编译class文件也可以看到。如下图:
2:父类和子类中静态代码块、非静态代码块、构造函数的执行顺序:
父类中的静态代码块→子类中的静态代码块→父类非静态代码块→父类构造函数→子类非静态代码块→子类构造函数
具体加载如下图:
所以,根据上面的分析,我们可以知道运行的结果:
父类B的中的静态代码块 子类A的中的静态代码块 父类B的中的非静态代码块 sya() 父类B的构造函数 子类A的中的非静态代码块 sya()1 子类A的构造函数 A! 父类B的中的非静态代码块 sya() 父类B的构造函数 子类A的中的非静态代码块 sya()1 子类A的构造函数 启动完成
总之一句话总结:
父类早于子类、静态早于非静态、非静态早于构造函数
相关推荐
本文将深度剖析几个常见的Java面试题目,包括方法重写、静态代码块和构造方法的执行顺序。 首先,我们来讨论**方法重写(Override)**。在面向对象编程中,子类可以继承父类的属性和方法,有时需要根据自己的需求对...
4.知道了static的作用,那么X类被加载,那么就会先执行X类的静态属性和静态语句块(static),执行先后顺序看谁在前面就先执行谁。只在此时执行,以后都不会。 5.所以一个输出结果为tttt,没问题了吧。 6.X类的...
这个顺序表明,无论类之间的继承关系如何,初始化顺序始终是:静态变量和静态初始化块先于非静态成员。在创建对象时,父类的初始化先于子类。这是Java语言规范所规定的,确保在子类访问父类的静态或非静态成员时,...
在本文中,我们将对 Java 面试题进行总结和分析,帮助读者快速掌握 Java 面试题的知识点。 一、 Java 基础知识 1. 面向对象的三个基本特征:封装、继承、多态 封装是把客观事物封装成抽象的类,并且类可以把自己的...
- 构造函数调用顺序:在子类构造函数中,如果未明确调用父类构造函数,则默认调用父类无参构造函数;若父类没有无参构造函数,则必须显式调用带参数的父类构造函数。 - 输出结果:由于`ChildClass`继承自`...
首先,需要了解Java类初始化的基本规则,即在类的静态变量、静态初始化块、变量、初始化块、构造器这五个部分中,它们的初始化顺序依次是:静态变量、静态初始化块、变量、初始化块、构造器。这个顺序在单个类中是...
1. **静态变量和静态初始化块**:无论是父类还是子类,静态变量和静态初始化块都会在类首次加载时按定义顺序依次执行。因此,输出顺序先是父类的静态部分,然后是子类的静态部分。 2. **实例化顺序**:在创建子类...
类的实例化顺序是:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类构造函数、子类非静态变量、子类构造函数。 6. HashMap和ConcurrentHashMap的区别: HashMap是非线程安全的...
为了在Java面试中脱颖而出,了解和掌握常见的面试题及答案至关重要。以下是一些关键知识点的详细解析: 1. **super()与 this()的区别** `super()`用于调用父类的构造器,确保子类实例化时父类的初始化;`this()`则...
这份"java面试题总结资料"涵盖了多个Java核心领域的关键知识点,包括但不限于: 1. **基础语法**:理解基本的数据类型(如整型、浮点型、字符型和布尔型),变量的声明与使用,以及运算符的优先级。同时,要熟悉...
子类的静态初始化块会在父类的静态初始化块之后执行,但非静态部分则有所不同,子类的非静态变量和初始化块会在父类的构造器之后执行。 对于静态变量和静态初始化块,以及非静态变量和非静态初始化块的顺序,它们并...
8. 类的初始化顺序:类的初始化顺序是父类静态成员变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数。...
12. **继承时的执行顺序**:通常涉及构造函数调用顺序和初始化顺序。 13. **内部类的实现方式**:包括成员内部类、局部内部类、匿名内部类等。 14. **实现序列化的方法**:通过实现`Serializable`接口或使用`...
继承时候类的执行顺序是先执行父类的静态代码块,然后执行子类的静态代码块,接着执行父类的实例代码块,最后执行子类的实例代码块。 12. 内部类的实现方式?: 内部类是指在另一个类中的类,可以是静态内部类或非...
总结来说,Java类的执行顺序涉及到类加载、验证、准备和初始化四个关键步骤,这些步骤在JVM内部协同工作,确保代码的正确性和安全性。理解这些基础知识对于编写高效、可靠的Java程序至关重要,也是面试中常见的技术...
3. **父类的非静态部分**:在创建子类实例时,首先执行父类的非静态变量初始化和非静态初始化块,然后调用父类的构造器。 4. **子类的非静态部分**:最后执行子类的非静态变量初始化和非静态初始化块,以及子类的...
"Java 核心面试题" 本文档总结了 Java 的基础知识和核心知识,涵盖了面向对象编程(OOP)、Java 线程、Java 集合类、垃圾收集器等方面的知识点。 面向对象编程(OOP) 面向对象编程是一种编程范式,它基于类和...
本资源摘要信息中,我们将总结 Java 面试笔试题中的知识点,涵盖 Java 基础、Java 集合框架、Java垃圾回收、Java 方法返回值、Java 对象引用、Java 构造函数执行顺序等方面的知识点。 一、Java 基础知识点 1. Java...
- 首先,父类的静态变量和静态初始化块会按照它们在类中出现的顺序执行。 - 接着,子类的静态变量和静态初始化块也会执行。 - 然后,父类的实例变量、实例初始化块、构造器按顺序执行。 - 最后,子类的实例变量、...
1. 创建第一个子类对象时:父类静态块->被调子类静态块->父类动态块->父类无参构造器->被调子类动态块->被调子类无参构造器 2. 创建第一个另一个子类对象时:被调子类静态块->父类动态块->父类无参构造器->被调子类...