静态数据初始化
无论创建多少对象,static都只有那么一片存储空间。不能对本地变量使用static关键字,只能对字段使用。如果静态的字段是原始类型(primitive)且没有被初始化,则该静态字段获得该类型的标准初始值。如果是某个对象的句柄,则默认初始值是null。正常初始化,和非静态字段一样。
static何时初始化,见下例:
//: initialization/StaticInitialization.java
// Specifying initial values in a class definition.
import static net.mindview.util.Print.*;
class Bowl {
Bowl(int marker) {
print("Bowl(" + marker + ")");
}
void f1(int marker) {
print("f1(" + marker + ")");
}
}
class Table {
static Bowl bowl1 = new Bowl(1); //1
Table() {
print("Table()"); //3
bowl2.f1(1); //4
}
void f2(int marker) {
print("f2(" + marker + ")");
}
static Bowl bowl2 = new Bowl(2); //2
}
class Cupboard {
Bowl bowl3 = new Bowl(3); //15 11 7
static Bowl bowl4 = new Bowl(4); //5
Cupboard() {
print("Cupboard()"); //16 12 8
bowl4.f1(2); //17 13 9
}
void f3(int marker) {
print("f3(" + marker + ")");
}
static Bowl bowl5 = new Bowl(5); //6
}
public class StaticInitialization {
public static void main(String[] args) {
print("Creating new Cupboard() in main"); //10
new Cupboard();
print("Creating new Cupboard() in main"); //14
new Cupboard();
table.f2(1); //18
cupboard.f3(1); //19
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
}
/* Output:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
*///:~
从结果可以看出,static初始化只在需要时进行。只有在创建了第一个Table对象(或第一次访问static时),才会初始化static。在这之后,static对象不会重新初始化(reinitialized)。
初始化的顺序是先static对象(如果没有在之前创建对象时初始化),再是非static对象
显式static初始化
Java允许我们将其他static初始化工作划分到类内一个特殊的“static构建从句(static clause)”(有时也叫作“静态块”(static block))里,例如:
//: initialization/Spoon.java
public class Spoon {
static int i;
static {
i = 47;
}
} ///:~
尽管看起来像是一个方法,但它实际只是一个static关键字,后面跟随一个方法主体
与其他static初始化一样,这段代码仅执行一次——首次生成那个类的一个对象时,或者首次访问属于那个类的一个static成员时(即便从未生成过那个类的对象)。例如:
class Cups {
static Cup cup1;
static Cup cup2;
static {
cup1 = new Cup(1);
cup2 = new Cup(2);
}
}
非静态实例初始化(Non-static instance initialization)
针对每个对象的非静态变量的初始化,Java 1.1提供了一种类似的语法格式。下面是一个例子:
public class Mugs {
Mug c1;
Mug c2;
{
c1 = new Mug(1);
c2 = new Mug(2);
}
System.out.println("c1 & c2 initialized");
}
看起来与静态初始化从句极其相似,只是static关键字从里面消失了。为支持对“匿名内部类”的初始化,必须采用这一语法格式