如果类中有多个构造函数都共享一段代码,并且各个构造函数之后不会调用其他的构造函数,那么可以将这段公共的代码放在初始化模块中。
初始化模块是用{}括起来的语句块,它位于类的声明中,但不是包括在类方法或者类的构造函数中的。
它的作用就是相当于将初始化模块放到每个构造函数的最开始位置,用于初始化对象。
一个类可以有多个初始化模块,执行顺序按照在类中出现的顺序执行。
类中的初始化模块包括实例初始化模块跟静态初始化模块
静态初始化模块是用static关键字修饰的初始化模块
实例初始化模块只有在创建类的实例时才会被调用,而静态初始化模块则是在类载入内存时调用。
注:类载入内存跟创建类的实例化不是相同的2个步骤,先是类的载入内存后才能实例化类的对象。
初始化模块的执行顺序:
第一次使用类时先将类载入内存:
如果类的父类没有载入内存则先将父类载入内存,这是一个递归过程,直到继承链上所有的父类都载入到内存中
当载入每个类时,类的静态数据域和静态初始化模块按照它们在类中出现的先后顺序执行
实例化类的对象时:
如果类的父类没有实例化,则先构造父类。这也是一个递归过程,直到继承链上所有的父类都构造好。
当构造每类时,按照类中出现的先后顺序执行实例数据域跟实例初始化模块
最后执行类的构造函数
如果声明类的实例变量有初始值,则变量的初始化就像在实例初始化模块中执行一样
如果声明类的静态变量有初始值,则变量的初始化也像在静态初始化模块中执行一样
例子:
public class InitializationDemo{
InitializationDemo(){
new M();
}
public static void main(String[] args){
new InitializationDemo();
}
{
System.out.println("(2) InitializationDemo's instance initialization block");
}
static{
System.out.println("(1) InitializationDemo's static initialization block");
}
}
class N{
N(){ System.out.println("(6) N's constructor body"); }
{
System.out.println("(5) N's instance initialization block");
}
static {
System.out.println("(3) N's static initialization block");
}
}
class M extends N{
M(){ System.out.println("(8) M's constructor body"); }
{
System.out.println("(7) M's instance initialization block");
}
static {
System.out.println("(4) M's static initialization block");
}
}