前段时间在做单例的时候遇到一个很奇怪的问题,前面已经初始化的参数,已经有值了,但是等到对象建立却发现值却为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
上面的代码基本上可以展示一个类从加载到产生对象的先后顺序,类加载时:静态属性顺序执行到静态代码块,产生对象时按非静态属性到执行构造函数顺序执行,至此一个对象完整产生。