class Bowl {
Bowl(int marker) { ---------------------3,5构造
System.out.println("Bowl(" + marker + ")");
}
void f(int marker) { ----------------------7,被table调用
System.out.println("f(" + marker + ")");
}
}
class Table {
static Bowl b1 = new Bowl(1); -----------------2,构造之前,也先static变量
Table() { -----------------6,变量已全部构造完成,执行构造函数
System.out.println("Table()");
b2.f(1); -----------------调用bow的f()
}
void f2(int marker) {
System.out.println("f2(" + marker + ")");
}
static Bowl b2 = new Bowl(2); ------------------4,第二个static变量的构造
}
class Cupboard {
Bowl b3 = new Bowl(3); -------------------11,static构造完后,构造非static成员
static Bowl b4 = new Bowl(4); -----------------9,先static成员构造
Cupboard() { ----------------12,成员已经构造好,执行构造函数
System.out.println("Cupboard()");
b4.f(2); --------------13,调用bow的f()
}
void f3(int marker) {
System.out.println("f3(" + marker + ")");
}
static Bowl b5 = new Bowl(5); ----------------10,按次序构造static成员
}
public class StaticInitialization {
public static void main(String[] args) {
System.out.println(
"Creating new Cupboard() in main"); -----------14,成员已经构造好,执行main函数体,首先执行此句
new Cupboard(); ------------------15,构造临时Cupboard对象
System.out.println(
"Creating new Cupboard() in main");
new Cupboard();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table(); -------------------1,先static变量
static Cupboard t3 = new Cupboard();-----------------8,继续构造static成员
}
运行结果如下
Bowl(1)
Bowl(2)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)
===========================
##static型的变量或者方法叫做类变量和类方法
类变量是在该类加载到内存的同时就进行初始化的
而非static变量是在产生实例时进行初始化
因为要执行一个static方法main(),因此要先把该类加载到内存并同时进行static变量的初始化
因此static Bowl bl = new Bowl(1);要在main函数开始执行之前就执行了
##看一下编译StaticInitialization.java的class目录,会发现虽然编译的只是一个.java文件,但由于java文件里声明了4个class,所以实际由这个java文件产生了4个class文件。
下面,你看是运行StaticInitialization.class,此时系统只载入这个类,其它三个类还没有载入,而在StaticInitialization.class有两句static语句,于是系统开始寻找这两句语句指定的类Table 和 Cupboard ,找到了开始载入,所以载入就发生了,自然也就开始初始化这两个类中的static。
##当类被装入jvm的时候,static的代码执行一次,以后就不再执行
##这个例子体现了类变量和实例变量的区别:
类变量即在变量前有"static"修饰,没有的即为实例变量;
类变量在每个类中只出现一次,不管这个类创建了多少实例,它使用的内存仅分配一次;
而实例变量是为类的每个实例分配的,在创建类的实例时,系统就为这个类中的所有实例变量分配内存。
在上面的例子中,由于b3是实例变量,所以每分配一个实例,就创建一个新的b3,所以它的输出是多次的
##构造类前先构造父类(如果父类还有父类,则先构造这个父类的父类,类推)
构造类的时候,先构造static变量(按代码顺序),构造完成后,构造非static变量
变量全部构造好以后,进入构造函数
##静态变量初始化是在类被初次调用的瞬间发生的,类中的非静态变量是在进入构造函数内部前初始化的,记住这两点,就可以很清楚地理解你的输出
当涉及到一个类时总会生成静态成员;然后若要生成这个类的实例,再调用initializer(默认的或人为创建的);调用构件器;完成创建。若运行一个类则会在初始化完静态成员后进入main这个入口,不会创建类的实例,除非在main的实现里有new出实例的代码。
##jvm先要构造静态对象,然后调用main(),,在对static的定义中指出,在编译时当装载一个类时会先装载其中的静态的方法。后才是构造方法。