参考资料
[1]. 疯狂Java讲义(第三版) 李刚
初始化块
初始化块与构造器作用非常类似,它也可以完成对Java对象进行初始化操作,它是在构造器之前执行。
使用初始化块
一个类里可以有多个初始化块,相同类型的初始化块之间按照从上向下的顺序执行。
语法如下:
[static]{
// 初始化块可执行的代码
...
}
使用了初始化块的代码:
public class Person
{
// 下面定义一个初始化块
{
int a = 6;
if (a > 4)
{
System.out.println("Person初始化块:局部变量a的值大于4");
}
System.out.println("Person的初始化块");
}
// 定义第二个初始化块
{
System.out.println("Person的第二个初始化块");
}
// 定义无参数的构造器
public Person()
{
System.out.println("Person类的无参数构造器");
}
public static void main(String[] args)
{
new Person();
}
}
普通初始化块、非静态的成员变量指定的默认值都是初始化代码,它们的执行顺序与源程序中的排列顺序相同,代码如下:
public class InstanceInitTest
{
int a = 9;
// 先执行初始化块将a实例变量赋值为6
{
a = 6;
}
// 再执行将a实例变量赋值为9
// int a = 9;
public static void main(String[] args)
{
// 下面代码将输出6。
System.out.println(new InstanceInitTest().a);
}
}
初始化块和构造器
初始化块是构造器的补充,初始化块总是在构造器执行之前执行,可以提取公共逻辑代码到初始化块,如下图:
一旦编译,Java类中的初始化块会被“还原”到每个构造器中,且位于构造器所有代码的前面。
静态初始化块
静态初始化块类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行,因此静态初始化块总是比普通初始化块先执行。
示例代码如下:
class Root
{
static{
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root()
{
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root
{
static{
System.out.println("Mid的静态初始化块");
}
{
System.out.println("Mid的普通初始化块");
}
public Mid()
{
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg)
{
// 通过this调用同一类中重载的构造器
this();
System.out.println("Mid的带参数构造器,其参数值:"
+ msg);
}
}
class Leaf extends Mid
{
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf()
{
// 通过super调用父类中有一个字符串参数的构造器
super("疯狂Java讲义");
System.out.println("执行Leaf的构造器");
}
}
public class Test
{
public static void main(String[] args)
{
new Leaf();
new Leaf();
}
}
执行上面的代码,将看到下面的输出
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:疯狂Java讲义
Leaf的普通初始化块
执行Leaf的构造器
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:疯狂Java讲义
Leaf的普通初始化块
执行Leaf的构造器
当第一次创建对象的时候会先加载并初始化这个类,执行其顶层父类的静态初始化块,然后是直接父类,最后是执行类的静态块。
静态初始化块和声明静态成员变量所指定的初始值都是该类的初始化代码,它们的执行顺序与源程序中的排列顺序相同,代码如下:
public class StaticInitTest
{
// 先执行静态初始化块将a静态成员变量赋值为6
static
{
a = 6;
}
// 再将a静态成员变量赋值为9
static int a = 9;
public static void main(String[] args)
{
// 下面代码将输出9
System.out.println(StaticInitTest.a);
}
}