Java中静态变量的初始化有关问题
Java中静态变量的初始化问题
/**
* java中的内存有一块地址叫"静态代码区",所有静态类都是放在这里的,静态类随jvm启动后就在那
* <p>
* 不会说程序停止了,它就被垃圾回收器回收,而new是实例化的命令,它会在java中的内存中的堆区,
* <p>
* 创建一个对象,注意它们的位置,一个是在 静态代码区,一个是在堆区,new出来的对象,一旦程序运行完,
* <p>
* 它就会被垃圾回收器回收.静态的,是不会消失了,只要jvm不关,就在一直在那.
*/
下面通过一个例子来加深对java静态变量的理解,这个例子相信想进一步了解java静态变量的同学,在很多地方都看见过:)
Order.java文件:
Bowl.java文件:
Cupboard.java文件:
Table.java文件:
运行结果:
分析:
首先程序从public类开始,装载Order,class,运行
static Cupboard t1 = new Cupboard();
由于t1是一个对象引用变量,首先得到初始化,然后转到Cupboard类的实例中,这时候程序开始初始化该实例中的变量,按照先static后非static变量初始化的顺序原则开始初始化各个变量,此时:
static Bowl b2 = new Bowl(2);
static Bowl b3 = new Bowl(3);
这两块先得到初始化,然后
Bowl b1 = new Bowl(1);得到初始化(注意,这是非stataic变量)
然后转到Cupboard() 构造函数.此时Cupboard类已经初始化完毕,程序返回到public类中,又发现有 static Table t2;开始初始化,由于t2只是个声明的变量,并没有创建一个Table对象让它指向,因此不要管这个t2变量.在public类中,由于此时再没有static变量可以初始化,那么程序转到static方法main中进行,(注意:Bowl t3 = new Bowl(10); 这一句为什么得不到初始化,是因为此时没有创建类Order的实例,所以程序目前还不会初始化该代码,至于以后会不会初始化,还要看在main方法中是否会创建Order类的实例,如创建了,则一定初始化,否则不会.)
在main方法中,System.out.println("Creating new Cupboard() in main");//首先打印该行要输出的语句new Cupboard(); //创建了Cupboard类的实例,程序转到Cupboard中进行变量初始化,此时要注意:
static变量的初始化,它只能初始化一次,也就是说,如果前面已经初始化过了,那么此时就不必要再初始化了.
/**
* java中的内存有一块地址叫"静态代码区",所有静态类都是放在这里的,静态类随jvm启动后就在那
* <p>
* 不会说程序停止了,它就被垃圾回收器回收,而new是实例化的命令,它会在java中的内存中的堆区,
* <p>
* 创建一个对象,注意它们的位置,一个是在 静态代码区,一个是在堆区,new出来的对象,一旦程序运行完,
* <p>
* 它就会被垃圾回收器回收.静态的,是不会消失了,只要jvm不关,就在一直在那.
*/
下面通过一个例子来加深对java静态变量的理解,这个例子相信想进一步了解java静态变量的同学,在很多地方都看见过:)
Order.java文件:
package com.ex; public class Order { static Cupboard t1 = new Cupboard(); static Table t2; Bowl t3 = new Bowl(10); void print() { t3.f1(); } public static void main(String[] args) { System.out.println("Creating new Cupboard() in main"); new Cupboard(); System.out.println("Creating new Cupboard() in main"); Order od = new Order(); od.t3.f1(); Table t4 = new Table("aa", 1); } }
Bowl.java文件:
package com.ex; public class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f1() { System.out.println("Ok"); } }
Cupboard.java文件:
package com.ex; public class Cupboard { Bowl b1 = new Bowl(1); /** 先static后非static变量初始化的顺序原则开始初始化各个变量. */ static Bowl b2 = new Bowl(2); Cupboard() { System.out.println("Cupboard()"); } static Bowl b3 = new Bowl(3); }
Table.java文件:
package com.ex; public class Table { Table() { System.out.println("Table()"); } Table(String a, int i) { this(); System.out.println("Ok"); } }
运行结果:
Bowl(2) Bowl(3) Bowl(1) Cupboard() Creating new Cupboard() in main Bowl(1) Cupboard() Creating new Cupboard() in main Bowl(10) Ok Table() Ok
分析:
首先程序从public类开始,装载Order,class,运行
static Cupboard t1 = new Cupboard();
由于t1是一个对象引用变量,首先得到初始化,然后转到Cupboard类的实例中,这时候程序开始初始化该实例中的变量,按照先static后非static变量初始化的顺序原则开始初始化各个变量,此时:
static Bowl b2 = new Bowl(2);
static Bowl b3 = new Bowl(3);
这两块先得到初始化,然后
Bowl b1 = new Bowl(1);得到初始化(注意,这是非stataic变量)
然后转到Cupboard() 构造函数.此时Cupboard类已经初始化完毕,程序返回到public类中,又发现有 static Table t2;开始初始化,由于t2只是个声明的变量,并没有创建一个Table对象让它指向,因此不要管这个t2变量.在public类中,由于此时再没有static变量可以初始化,那么程序转到static方法main中进行,(注意:Bowl t3 = new Bowl(10); 这一句为什么得不到初始化,是因为此时没有创建类Order的实例,所以程序目前还不会初始化该代码,至于以后会不会初始化,还要看在main方法中是否会创建Order类的实例,如创建了,则一定初始化,否则不会.)
在main方法中,System.out.println("Creating new Cupboard() in main");//首先打印该行要输出的语句new Cupboard(); //创建了Cupboard类的实例,程序转到Cupboard中进行变量初始化,此时要注意:
static变量的初始化,它只能初始化一次,也就是说,如果前面已经初始化过了,那么此时就不必要再初始化了.
1 楼
edison_cool911
2011-10-24
连我都看的懂,相信一般的同学都看的懂了,O(∩_∩)O哈哈~