public class MainTest { 
public static void main(String[] args) { 
Singleton obj = Singleton.getInstance(); 
System.out.println("obj.counter1==" + obj.counter1); 
System.out.println("obj.counter2==" + obj.counter2); 

} class Singleton { 
private static Singleton obj = new Singleton(); 
public static int counter1; 
public static int counter2 = 0; private Singleton() { 
counter1++; 
counter2++; 
} public static Singleton getInstance() { 
return obj; 

} 结果为:obj.counter1==1
obj.counter2==0问题:为什么后者的counter2会是0而不是1?

解决方案 »

  1.   

    类加载分别经历三个阶段,
    其中链接阶段有一个步骤是初始化为默认值
    经历了链接阶段后,obj =null,counter1=0,counter2=0
    最后阶段是初始化阶段,就是给静态变量赋予用户给的值,如果用户没给值就默认值
    经历初始化阶段
    首先new obj使得counter1 = 1,counter2 = 1
    然后分别按顺序给其他静态变量赋值,counter1还是1,counter2被赋予0了
      

  2.   

    这个涉及到类的初始化和类成员变量初始化的顺序
    当 Singleton.getInstance(); 这个静态方法被调用时,这将导致该类的Class对象进行静态成员变量和静态代码块初始化.
    首先 Singleton类的 静态成员变量obj被默认静态初始化为null,静态成员变量counter1和counter2 也都默认初始化为0静态变量初始化后,将执行类定义处的初始化
    Singleton obj = new Singleton();这时候将调用类的构造方法
    private Singleton() {  
    counter1++;  
    counter2++;  
    }  
    此时counter1和counter2均为1,接着初始类定义中的counter1值,它没有被手动初始为其他值,它仍就是1.counter2被初始赋为0,所以counter2被重新初始赋值为0所以你最后的结果就是1和0
      

  3.   

    一个类的执行顺序是,类加载的时候执行静态代码块,生成实例的时候执行初始化块,然后再执行构造函数

    class A {
        {System.out.println("seconde");}
        static {System.out.println("first");}
        public A() {System.out.println("third");}
        public static void main(String[] args) {
            new A();
        }
    }private static Singleton obj = new Singleton();  
    相当于
    private static Singleton obj;
    static {obj = new Singleton();} //静态代码块1public static int counter2 = 0;  
    相当于
    public static int counter2;
    static {counter2 = 0;} //静态代码块2所以,从代码执行顺序知道,先执行 static {obj = new Singleton();} //静态代码块1
    这里会调用构造方法,使得counter1=1,counter2=1
    接着执行 static {counter2 = 0;} //静态代码块2
    使得counter2=0