用构建器执行初始化进程。这样便可在编程时获得更大的灵活程度,因为我们可以在运行期调用方法和采取行动,从而“现场”决定初始化值。但要注意这样一件事情:不可妨碍自动初始化的进行,它在构建器进入之前就会发生。因此,假如使用下述代码:
class Counter { int i; Counter() { i = 7; } // . . .
那么 i 首先会初始化成零,然后变成7。对于所有基本类型以及对象 句柄 ,这种情况都是成立的,其中包括在定义时已进行了明确初始化的那些一些。考虑到这个原因,编译器不会试着强迫我们在构建器任何特定的场所对元素进行初始化,或者在它们使用之前——初始化早已得到了保证。
初始化顺序
在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。即使变量定义大量遍布于方法定义的中间,那些变量仍会在调用任何方法之前得到初始化——甚至在构建器调用之前。
静态数据的初始化
若数据是静态的( static ),那么同样的事情就会发生;如果它属于一个基本类型(主类型),而且未对其初始化,就会自动获得自己的标准基本类型初始值;如果它是指向一个对象的句柄,那么除非新建一个对象,并将句柄同它连接起来,否则就会得到一个空( NULL )。
如果想在定义的同时进行初始化,采取的方法与非静态值表面看起来是相同的。但由于 static 值只有一个存储区域,所以无论创建多少个对象,都必然会遇到何时对那个存储区域进行初始化的问题。 static 初始化只有在必要的时候才会进行。如果不创建一个 Table 对象,而且永远都不引用 Table.b1 或 Table.b2 ,那么 static Bowl b1 和 b2 永远都不会创建。然而,只有在创建了第一个 Table 对象之后(或者发生了第一次 static 访问),它们才会创建。在那以后, static 对象不会重新初始化。初始化的顺序是首先 static (如果它们尚未由前一次对象创建过程初始化),接着是非 static 对象。
在这里有必要总结一下对象的创建过程。请考虑一个名为Dog的类:
- 类型为 Dog 的一个对象首次创建时,或者 Dog 类的 static 方法/ static 字段首次访问时, Java 解释器必须找到 Dog.class
- 找到 Dog.class 后(它会创建一个 Class 对象),它的所有 static 初始化模块都会运行。因此, static 初始化仅发生一次——在 Class 对象首次载入的时候。
- 创建一个 new Dog() 时, Dog 对象的构建进程首先会在内存堆( Heap )里为一个 Dog 对象分配足够多的存储空间。
- 这种存储空间会清为零,将 Dog 中的所有基本类型设为它们的默认值(零用于数字,以及 boolean 和 char 的等价设定)。
- 进行字段定义时发生的所有初始化都会执行。
- 执行构建器。