1、Java程序的初始化顺序
在 Java 语言中,当实例对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在的构造函数创建对象。
Java 程序的初始化一般遵循以下三个原则:
- 静态对象(变量)、非静态对象(变量)。
- 父类优先于子类进行初始化。
- 按照成员变量定义顺序进行初始化。
Java 程序的初始化工作可以在许多不同的代码块中来完成,例如:静态代码块、实例语句块、构造函数等。
1.1 普通类的执行顺序
普通类的执行顺序为:静态代码块 → 实例语句块 → 构造函数。
【示例】普通类的执行顺序。
(1)创建普通类
/**
* 普通类
* @author pan_junbiao
**/
public class MyClass
{
//静态代码块
static
{
System.out.println("静态代码块");
}
//实例语句块
{
System.out.println("实例语句块");
}
//构造函数
public MyClass()
{
System.out.println("构造函数");
}
}
(2)执行方法
/**
* Java普通类的执行顺序
* @author pan_junbiao
*/
public static void main(String[] args)
{
//创建普通类对象
MyClass myClass = new MyClass();
}
执行结果:
1.2 继承类的执行顺序
继承类的执行顺序为:父类静态代码块 → 子类静态代码块 → 父类实例语句块 → 父类构造函数 → 子类实例语句块 → 子类构造函数。
【示例】继承类的执行顺序。
(1)创建父类
/**
* 父类
* @author pan_junbiao
**/
public class Parent
{
//静态代码块
static
{
System.out.println("父类静态代码块");
}
//实例语句块
{
System.out.println("父类实例语句块");
}
//构造函数
public Parent()
{
System.out.println("父类构造函数");
}
}
(2)创建子类
/**
* 子类
* @author pan_junbiao
**/
public class Child extends Parent
{
//静态代码块
static
{
System.out.println("子类静态代码块");
}
//实例语句块
{
System.out.println("子类实例语句块");
}
//构造函数
public Child()
{
System.out.println("子类构造函数");
}
}
(3)执行方法
/**
* Java继承类的执行顺序
* @author pan_junbiao
*/
public static void main(String[] args)
{
//创建子类对象
Child child = new Child();
}
执行结果:
1.3 成员变量初始化的优先级
这里需要注意的是,(静态)非静态成员域在定义时初始化和(静态)非静态块中初始化的优先级是平级的,也就是说按照从上到下初始化,最后一次初始化为最终的值(不包括非静态的成员域在构造器中初始化)。所以在(静态)非静态块中初始化的域甚至能在该域声明的上方,因为分配存储空间在初始化之前就完成了。
【示例】(静态)非静态块中成员变量初始化的优先级。
/**
* (静态)非静态块中成员变量初始化的优先级
* @author pan_junbiao
**/
public class TestStatic
{
static { a = 2;}
static int a = 1;
static int b = 3;
static { b = 4; }
public static void main(String[] args)
{
System.out.println("初始化后的变量的值:");
System.out.println(a);
System.out.println(b);
}
}
执行结果:
2、static{}静态代码块的使用
static{} 静态代码块在类的加载时执行,并且只执行一次,且在 main 方法之前执行。一个类中可以有多个静态代码块,执行顺序自上而下。一个静态代码块只能访问该静态代码块之前的静态变量。
static{} 静态代码块在类初次被加载的时候执行且仅会被执行一次,所以可以起到优化程序性能的作用。
static{} 静态代码块的语法:
//静态代码块
static
{
//Java程序
}
3、实例语句块的使用
除了static{} 静态代码块之外,还有一种语句块叫做:实例语句块。
顾名思义,就是在实例化对象时执行,并不是在类加载时执行。
实例语句块的具体执行时间是在实例化对象时的构造函数之前执行的。
实例语句块的语法:
//实例语句块
{
//Java程序
}
4、练习题目
最后来一道题目练习一下关于 static{} 静态代码块、实例语句块和构造函数的执行顺序。例题如下:
/**
* 判断以下程序的执行顺序
* @author pan_junbiao
**/
public class CodeOrder
{
//静态代码块
static
{
System.out.println("A");
}
//程序入口
public static void main(String[] args)
{
System.out.println("Y");
new CodeOrder();
System.out.println("Z");
}
//构造函数
public CodeOrder()
{
System.out.println("B");
}
//实例语句块
{
System.out.println("C");
}
//静态代码块
static
{
System.out.println("X");
}
}
执行结果: