1.普通变量的初始化 看如下程序 [html] class Window{ public Window(int maker) { System.out.println('Window('+maker+')'); } } class House{ Window w1 = new Window(1); public House() { System.out.println('House()'); w3 = new Window(33); } Window w2 = new Window(2); void f(){ System.out.println('f()'); } Window w3 = new Window(3); } public class Test { public static void main(String[] args) { House h = new House(); h.f(); } } /* 结果如下: Window(1) Window(2) Window(3) House() Window(33) f() */ 分析:普通变量在类中的任何方法(包括构造函数)之前初始化(规则一)。 2.静态变量的初始化 [html] class Bowl{ public Bowl(int maker) { System.out.println('Bowl('+maker+')'); } void f1(int maker){ System.out.println('f1('+maker+')'); } } class Table{ static Bowl bowl1 = new Bowl(1); static Bowl bowl2 = new Bowl(2); public Table() { System.out.println('Table()'); bowl2.f1(1); } void f2(int maker){ System.out.println('f2('+maker+')'); } } class Cupboard{ Bowl bowl3 = new Bowl(3); static Bowl bowl4 = new Bowl(4); static Bowl bowl5 = new Bowl(5); public Cupboard() { System.out.println('cupboard()'); bowl4.f1(2); } void f3(int maker){ System.out.println('f3('+maker+')'); } } public class Test { static Table table = new Table(); static Cupboard cupboard = new Cupboard(); public static void main(String[] args) { System.out.println('creating new cupboard() in main'); new Cupboard(); System.out.println('creating new cupboard() in main'); new Cupboard(); table.f2(1); cupboard.f3(1); } } /* 结果如下: 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) */ 分析: 1.首先程序总共有4个类(Bowl,Table,Cupboard,Test),Bowl没有静态变量和静态方法;Table中有静态变量bowl1、bowl2;Cupboard中有普通变量bowl3,静态变量bowl4、bowl5;Test中有静态变量table、cupboard。 2.根据规则:使用static命名的变量或者使用static{}包括起来的区域,都在类被加载时进行初始化(规则二)。 3.虚拟机首先加载Test,需要初始化table变量,加载Table类。Table类中有静态变量bowl1,bowl2,初始化它们,输出'Bowl(1),Bowl(2)',再调用构造函数来new对象,输出'Table(),f1(1)'。然后加载Cupboard类,初始化静态变量bowl4,bowl5,输出'Bowl(4),Bowl(5)',调用构造函数来new对象,首先初始化普通变量bowl3,输出'Bowl(3)',然后构造函数,输出'cupboard(),f1(2)'。 4.执行main方法,先输出'creating new cupboard() in main',执行new Cupboard(),这时静态变量都初始化了,不必继续初始化。初始化一般变量bowl3,输出'bowl3',然后调用构造函数,输出'cupboard(),f1(2)'。在输出'creating new cupboard() in main',同理输出'bowl3,cupboard(),f1(2)',最后继续执行main函数,输出'f2(1),f3(1)'。 3.静态代码块的初始化 [html] class Spoon{ public Spoon(int maker) { System.out.println('Spoon('+maker+')'); } static int i; static Spoon s = new Spoon(1); static{ System.out.println('static code '); i = 47; } } public class Test { public static void main(String[] args) { new Spoon(2); } } /* Spoon(1) static code Spoon(2) */ /* 如果写成 static{ System.out.println('static code '); i = 47; } static Spoon s = new Spoon(1); 结果为: static code Spoon(1) Spoon(2) */ 分析:静态代码块跟静态变量都是类加载时进行初始化的(同等条件下,初始化顺序由书写顺序决定) 4.非静态代码块 [html] class Spoon{ public Spoon(int maker) { System.out.println('Spoon('+maker+')'); } static int i; static Spoon s = new Spoon(1); static{ System.out.println('static code '); i = 47; } int a; //非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中 { System.out.println('non-static instatnce'); a = 1; } } public class Test { public static void main(String[] args) { new Spoon(2); new Spoon(3); } } /* non-static instatnce Spoon(1) static code non-static instatnce Spoon(2) non-static instatnce Spoon(3) */ 分析: 1.main函数执行new Spoon(2)语句,首先加载Spoon类,先初始化静态变量s,s调用new Spoon(1),此时类Spoon已经加载,所以不用管静态变量和静态代码块了,然后调用非静态代码块和构造函数,输出'non-static code,spoon(1)'。 2.初始化静态代码块,输出'static code'。 3.执行new spoon(2)语句输出“non-static instatnce,Spoon(2)“。 4.执行'new spoon(3)'语句输出”non-static instatnce,Spoon(3)”。 可以尝试调换静态变量s和静态代码块的顺序,发现只是1和2的先后顺序改变而已。 在看下面这个程序 [cpp] class T{ public T() { System.out.println('T constructor'); } } class Spoon{ public Spoon(int maker) { System.out.println('Spoon('+maker+')'); } int a; //非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中 { System.out.println('non-static instatnce'); a = 1; } T t1 = new T(); } public class Test { public static void main(String[] args) { new Spoon(2); } } /* non-static instatnce T constructor Spoon(2) */ 通过这个程序,可以发现非静态变量和非静态代码块顺序由书写顺序决定。 5.总结: 以Dog类为例 1.当第一次执行到需要使用Dog类时(如Dog d = new Dog),java首先通过寻找classpath来找到Dog.class,进行加载. 2.初始化Dog类的静态变量和静态代码块(按书写顺序,若静态变量或代码块中还有new Dog,此时不用再管静态变 量和代码块了,如第五个程序中的'static Spoon s = new Spoon(1)')。 3.系统给类分配足够大的内存空间,初始化非静态变量和非静态代码块(顺序由书写顺序决定) 4.最后执行Dog类的构造函数。 5.以后如果还要new Dog类对象时(不是第一次使用了),重复3和4的步骤,不会再去初始化静态变量和静态代码 块了。 大家可以自己写程序实验一下。 6.子类继承父类时的初始化顺序 1.系统启动时,首先初始化父类和子类的static变量和块 2.初始化父类的普通变量,调用父类的构造函数 3.初始化子类的普通变量,调用子类的构造函数 7.附记 由于个人能力有限,第一次学习只了解这些了,有什么错误,请多多指教。 http://www./Javabc/620714.htmlwww.truehttp://www./Javabc/620714.htmlTechArticle1.普通变量的初始化 看如下程序 [html] class Window{ public Window(int maker) { System.out.println(Window(+maker+)); } } class House{ Window w1 = new Window(1); public Ho...
|
|