前面已经讲过两种初始化数据域的方法:
- 在构造器中设置值
- 在声明中复制
实际上,java还有第三种机制,称为初始化块.在一个类的声明中,可以包含对个代码块.只要构造类的对象,这些块就会被执行.例如
class Employee{ private static int nextId; private int id; private String name; private double salary; //初始化块 { id = nextId; nextId++; } public Employee(String n,double s){ name = n; salary = s; } public Employee(){ } .... }
在这个实例中,无论使用那个构造器构造对象,id域都在对象初始化块中被初始化.首先运行初始化块,然后才运行构造器的主体部分.
初始化的顺序是类定义的顺序,因此建议将初始化块放在域定义之后.
由于初始化数据域有多种途径,所以列出构造过程的所有路径可能相当混乱.下面是调用构造器的具体处理步骤:
- 所有数据域被初始化为默认值(0,false或null).
- 按照在类声明中出现的次序,依次执行所有域初始化语句和初始化块
- 如果构造其第一行调用了第二个构造器,则执行第二个构造器主体
- 执行当前构造器主体
当然,应该精心地组织好初始化代码,这样有利于维护.例如,如果让类的构造器行为依赖于数据域声明的顺序,那么就会显得很奇怪并且容易引起错误.
可以通过提供一个初始化值,或者使用一个静态的初始化块来对静态域进行初始化.前面已经介绍过第一种机制:
private static int nextId = 1;
如果对类的静态域进行初始化的代码比较复杂,那么可以使用静态的初始化块.
将代码放在一个块中,并标记关键字static
static { Random generator = new Random(); nextId = generator.nextId(10000); }
在类第一次加载时,将会进行静态域的初始化.与实例域一样,除非将他们显示地设置成其他值,否则默认的初始化值是0,false或null.所有的静态初始化语句以及静态初始化快都将依照类定义的顺序执行.