前段时间在做单例的时候遇到一个很奇怪的问题,前面已经初始化的参数,已经有值了,但是等到对象建立却发现值却为null了,随便debug跟踪下看看到底是怎么回事。
解释示例代码如下
public class Demo { private static int i=0; private static String msg =""; private static Demo d=new Demo();//这样写确实很怪异,只是为说明顺序而写在这里 private static String DRIVER=null; private static String URL=null; private static String USERNAME=null; private static String PASSWORD=null; private String demoString="abc"; static{ System.out.print("执行了类的静态块,在类的静态块里面为USERNAME赋值----"); USERNAME="USERNAME"; //do something System.out.print("类加载时,因DRIVER在d后声明,后经DRIVER声明后值为"+DRIVER);//此时DRIVER值为null System.out.print(" USERNAME为:"+USERNAME+"--------");//USERNAME为USERNAME System.out.println("类加载时不对非静态的属性进行加载,因此demoString在此不可用"); //System.out.println(demoString);类加载时不对非静态的属性进行加载,因此demoString在此不可用 } public Demo(){ System.out.print("调用了构造函数,在构造函数中为DRIVER赋值------"); DRIVER="DRIVER"; //do something i++; if(i==1) msg="类加载初始化属性时,因声明d是一个Demo对象调用了构造函数因此"; else msg="产生对象时,因类加载时已经执行过USERNAME初始化,且产生对象又调用了构造函数,因此"; System.out.print(msg+"DRIVER为:"+DRIVER);//此时DRIVER值为DRIVER System.out.print(" USERNAME为:"+USERNAME+"-----");//USERNAME为null System.out.println("构造函数时对象开始产生,非静态的属性被解释"+demoString);//构造函数时对象开始产生,非静态的属性被解释 } public String test() { //do something 类加载和产生对象时不会执行,当调用时才执行 return null; } public static String test1() { //do something 类加载和产生对象时不会执行,当调用时才执行 return null; } }
测试代码
public class XmlMain { /** * @param args */ public static void main(String[] args) { Demo dd=new Demo(); } } 打印结果: 调用了构造函数,在构造函数中为DRIVER赋值------类加载初始化属性时,因声明d是一个Demo对象调用了构造函数因此DRIVER为:DRIVER USERNAME为:null-----构造函数时对象开始产生,非静态的属性被解释demoString=abc 执行了类的静态块,在类的静态块里面为USERNAME赋值----类加载时,因DRIVER在d后声明,后经DRIVER声明后值为null USERNAME为:USERNAME--------类加载时不对非静态的属性进行加载,因此demoString在此不可用 调用了构造函数,在构造函数中为DRIVER赋值------产生对象时,因类加载时已经执行过USERNAME初始化,且产生对象又调用了构造函数,因此DRIVER为:DRIVER USERNAME为:USERNAME-----构造函数时对象开始产生,非静态的属性被解释demoString=abc
上面的代码基本上可以展示一个类从加载到产生对象的先后顺序,类加载时:静态属性顺序执行到静态代码块,产生对象时按非静态属性到执行构造函数顺序执行,至此一个对象完整产生。