在Java语言中,当实例化一个对象时,首先需要对对象中的所有成员变量进行初始化,这些成员变量可能包括静态变量和非静态变量,只有当类中所有的成员变量都初始化完后,才会调用类的构造函数创建具体的对象。
一个Java类中,可能既有静态变量,也有非静态变量,同时可能存在静态代码块,以及非静态代码块,比如下面的 Test.java 类:
public class Test { private static final int DEFAULT_SIZE = 1; private String name; static { System.out.println("Hello World!"); } { System.out.println("Today is Friday!"); } public Test() { } }对于Java程序,初始化一般遵循以下几个原则(优先级依次递减):
(1)静态对象(变量)优先于非静态对象(变量)初始化,其中,静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次;
(2)静态代码块优先于非静态代码块初始化;
(3)父类优先于子类进行初始化;
(4)按照成员变量的定义顺序进行初始化,即使变量定义散布于方法定义之中,它们依然在任何方法(包括构造函数)被调用之前先初始化;
Java程序初始化工作,可以在许多不同的代码块中来完成,例如静态代码块、构造函数等,它们执行的顺序如下:
父类静态变量 --》父类静态代码块 --》子类静态变量 --》子类静态代码块 --》父类非静态变量 --》父类非静态代码块 --》父类构造函数 --》子类非静态变量 --》子类非静态代码块 --》子类构造函数。
下面给出一个不同模块初始化时执行顺序的一个例子,首先定义一个父类 Parent.java:
public class Parent { static { System.out.println("Parent static block"); } { System.out.println("Parent block"); } public Parent() { System.out.println("Parent constructor block"); } }再定义一个子类 Child.java,它继承于 Parent.java,如下:
public class Child extends Parent { static { System.out.println("Child static block"); } { System.out.println("Child block"); } public Child() { System.out.println("Child constructor block"); } }下面创建一个 Child 对象进行测试验证,看看初始化顺序到底是怎样的?
public static void main(String[] args) { Child child = new Child(); }运行后,输出结果如下:
Parent static block Child static block Parent block Parent constructor block Child block Child constructor block::: hljs-center
:::
更多有关Java面试相关的知识点可以关注【Java面试手册】小程序,涉及Java基础、多线程、JVM、Spring、Spring Boot、Spring Cloud、Mybatis、Redis、数据库、数据结构与算法等。
::: hljs-center
:::