java中普通变量、静态变量、静态代码块初始化的顺序辨析
来源:互联网 发布:051级驱逐舰知乎 编辑:程序博客网 时间:2024/04/30 15:00
1.普通变量的初始化
看如下程序
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.静态变量的初始化
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 mainBowl(3)cupboard()f1(2)creating new cupboard() in mainBowl(3)cupboard()f1(2)f2(1)f3(1)*/<span style="color:#ff0000"></span>分析:
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.静态代码块的初始化
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.非静态代码块
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 instatnceSpoon(1)static code non-static instatnceSpoon(2)non-static instatnceSpoon(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的先后顺序改变而已。
在看下面这个程序
<span style="font-size:18px">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 instatnceT constructorSpoon(2) */</span>
通过这个程序,可以发现非静态变量和非静态代码块顺序由书写顺序决定。
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://blog.csdn.net/wanghao109
8.Other
总结《java编程思想》中的3条原则:
1.所有初始化都在构造器被调用之前发生
2.静态初始化只有在必要时才会进行(如第一次创建类对象,第一次访问类的静态数据等)
3.初始化顺序一般是先静态,后非静态
- java中普通变量、静态变量、静态代码块初始化的顺序辨析
- java中普通变量、静态变量、静态代码块初始化的顺序辨析
- java中普通变量、静态变量、静态代码块初始化的顺序辨析
- java中普通变量、静态变量、静态代码块初始化的顺序 收录总结
- Java中静态变量、块、非静态变量、块和构造器的初始化顺序
- Java中静态代码块,静态变量,静态方法,构造方法初始化顺序
- JAVA中代码顺序,静态块 静态变量,加载顺序!
- Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造方法)
- Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器
- Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)
- Java中静态块,静态成员变量,构造块,普通成员变量,构造方法的执行顺序
- java 静态变量 静态代码初始化块 构造函数的顺序
- java基础,静态变量,静态初始化块,初始化快,成员变量的初始化顺序
- Java 静态变量、静态代码块初始化的时机
- Java普通代码块,构造代码块,静态代码块,成员变量的执行顺序的代码实例
- Java中变量、代码块与静态块调用顺序
- java中静态的代码块,静态变量,静态方法
- java中静态的代码块,静态变量,静态方法
- CALayer相关
- 专业学习的成果
- const修饰符的作用
- VC学习:虚拟按键的总结及示例
- struts基本流程
- java中普通变量、静态变量、静态代码块初始化的顺序辨析
- xcode4.5 如何找到以前的iphone模拟器
- iPhone/iOS Core Animation开发总结(CALayer) 分类: iphone开发总结
- 【转】MFC的运行机制 以及 MFC中的DC、CDC、HDC、句柄、设备上下文(整理)
- 解决servlet调用spring中bean的问题
- java String byte 16
- 使用PHP程序header location 进行跳转的注意的一个细节!
- AppleScript 脚本让 Mac 唱生日快乐歌
- opengl toturial 2, "Impossible to open SimpleVertexShader.vertexshader"