java中普通变量、静态变量、静态代码块初始化的顺序辨析

原创 2016年05月31日 23:43:50
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)  
  
*/<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.静态代码块的初始化
 
 
[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] 
<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 instatnce 
T constructor 
Spoon(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.初始化子类的普通变量,调用子类的构造函数
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

java中普通变量、静态变量、静态代码块初始化的顺序辨析

1.普通变量的初始化 看如下程序 class Window{ public Window(int maker) { System.out.println("Window("+maker+")...

java中普通变量、静态变量、静态代码块初始化的顺序 收录总结

class Window{ public Window(int maker) { System.out.println("Window("+maker+")"); ...

Java初始化顺序总结及其程序执行过程图- 静态变量、静态代码块、成员变量、构造函数

Java初始化顺序 1在new B一个实例时首先要进行类的装载。(类只有在使用New调用创建的时候才会被java类装载器装入) 2,在装载类时,先装载父类A,再装载子类B 3,装载父类A后,完成静态动...

java中的静态变量、静态方法与静态代码块详解与初始化顺序

我们知道类的生命周期分为装载、连接、初始化、使用和卸载的五个过程。 其中静态代码在类的初始化阶段被初始化。 而非静态代码则在类的使用阶段(也就是实例化一个类的时候)才会被初始化。 静态变...

this、static关键字(静态变量、方法、代码块)| 单例模式

this 关键字 static关键字 静态变量 单例模式

Java中变量、代码块与静态块调用顺序

Java变量、代码块与静态块调用顺序的解析

静态代码块、静态变量、构造代码块、构造方法的执行顺序

最近项目经理要我整理一下java基础,找个重点讲一下,刚好最近在研究关于静态static的东西,所以拿出来先分享一下。 首先讲一下java中有关静态代码块、静态变量、构造代码块、构造方法的定义。 静态...
  • kuku713
  • kuku713
  • 2013年09月25日 16:08
  • 1055

静态变量、静态代码块、变量、代码块、构造函数执行顺序

一直对着个不太理解,最近总结了下,如果有不对的,请大家给指正 执行的先后顺序(同一等级按代码的顺序执行) 1.静态变量、静态代码块 2.变量、代码块 3.构造函数 public cl...

Java 静态变量的初始化顺序

1  无继承情况下的Java初始化顺序: class Sample {       Sample(String s)       {             System.out.pri...

JAVA中的Static(静态变量、静态方法、静态代码块)

只要是接触编程语言(C、C++、C#、java等等),static这个关键字相信程序猿朋友们都曾经深刻的理解过其含义,以前遇到的静态方法,静态变量还能理解,但是在碰到static代码块时候懵了,完全不...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java中普通变量、静态变量、静态代码块初始化的顺序辨析
举报原因:
原因补充:

(最多只允许输入30个字)