今天和同事争论一问题,关于静态变量与非静态变量的初始化顺序,谁先谁后,最终想整理出来!
测试代码:
import java.util.Map; public class T { public static T t = new T(); private Map map = new HashMap(); public T(){ System.out.println("Map的值: "+map); } public static void main(String[] args) { System.out.println(t); System.out.println(t.map); } }
运行结果:
Map的值: null
cn.com.algorithm.T@de6ced
{}
为什么Map的值为null,而如果把private static Map map = new HashMap();中的static 去掉,则运行结果为:
Map的值: {}
cn.com.algorithm.T@c17164
{}
所以他觉得非静态变量是在静态变量之前初始化的,这个我太怀疑了,是这样吗?
下面用测试类来证明些实事:
public class Demo1 { public Demo1(){ System.out.println("Demo1的构造函数执行"); } }
public class Demo2 { public Demo2(){ System.out.println("Demo2的构造函数执行"); } }
public class Demo3 { public Demo3(){ System.out.println("Demo3的构造函数执行"); } }
运行(java -verbose 类名 可以看出来什么时候加载了哪些类):
D:\test>javac TestClassLoaderTime.java
D:\test>java -verbose TestClassLoaderTime > result.txt
result.txt数据片断 [Loaded TestClassLoaderTime from file:/D:/test/] [Loaded Demo2 from file:/D:/test/] Demo2的构造函数执行 --------main方法开始了------------ [Loaded Demo1 from file:/D:/test/] Demo1的构造函数执行 --------Demo1实例化过------------ [Loaded Demo3 from file:/D:/test/] Demo3的构造函数执行 --------TestClassLoaderTime实例化过------------ [Loaded java.util.AbstractList$Itr from shared objects file]
说明:
1. Demo2 在 Demo1之前被类加载器加载,说明类的静态变量只有在实例化时才去加载
2. Demo3 在 Demo2 之后被类加载器加载,而且Demo3是在类TestClassLoaderTime实例化后才加载的,而Demo2是在main方法执行前被加载,说明静态变量比非静态变量先初始化!
如果修改测试类为:
public class TestClassLoaderTime { public TestClassLoaderTime(){ System.out.println("构造器执行"); } { System.out.println("静态代码块执行"); } static Demo2 demo2 = new Demo2(); Demo3 demo3 = new Demo3(); public static void main(String[] args) { System.out.println("main方法执行"); new TestClassLoaderTime(); System.out.println("TestClassLoaderTime实例化过"); } }
运行结果:
Demo2的构造函数执行 main方法执行 静态代码块执行 Demo3的构造函数执行 构造器执行 TestClassLoaderTime实例化过
说明JAVA中初始化的顺序:
加载类、 静态成员变量初始化、 静态代码块、非静态成员变量初始化、 构造方法;
所以对于文章开头的问题,你有自己的答案了吗?