经过下面的例子,验证类的启动方式.net
class SingletonOne { private static SingletonOne singletonOne = new SingletonOne(); public static int counter1; public static int counter2 = 0; private SingletonOne() { counter1++; counter2++; } public static SingletonOne getSingletonOne() { return singletonOne; } } class SingletonTwo { public static int counter1; public static int counter2; private static SingletonTwo singletonTwo = new SingletonTwo(); private SingletonTwo() { counter1++; counter2++; } public static SingletonTwo getSingletonTwo() { return singletonTwo; } } public class TestClassLoaderOrder { public static void main(String[] args) { System.out.println("singletonOne count1 = " + SingletonOne.counter1); System.out.println("singletonOne count2 = " + SingletonOne.counter2); System.out.println("singletonTwo count1 =" + SingletonTwo.counter1); System.out.println("singletonTwo count2 =" + SingletonTwo.counter2); } }
以上代码,SingletonOne和SingletonTwo 两个类的代码惟一的区别就是code
public static int counter1;blog
public static int counter2;接口
private static SingletonTwo singletonTwo = new SingletonTwo();get
两段代码的顺序,可是就是不一样的顺序产生不一样的结果虚拟机
singletonOne count1 = 1class
singletonOne count2 = 0变量
singletonTwo count1 =1反射
singletonTwo count2 =1方法
SingletonTwo 容易理解,下面来探讨一个为何SingletonOne 里的count2为何会是“0” 由文章开头所说,访问某个类或接口的静态变量,或者对该静态变量赋值就会对类进行加载,在System.out.println()里面均访问了类的静态变量,因此两个类都会进行加载。 SingletonOne 类在启动时,会经历,加载,链接,初始化的阶段,链接的时候,也分三步,验证,准备,解析,在之前博文有提过http://www.javashuo.com/article/p-rxjinmbo-hr.html 准备的时候,会给静态变量初始化默认值,这时首选counter1和counter2都是给默认值0 此时
counter1 = 0;
counter2 = 0;
紧接着进入类的初始化阶段,第一段代码执行调用了构造方法两个值均相加1
counter1 = 1;
counter2 = 1;
在下面,count1只是声明,不会对值改变,而count2会给此变量从新初始化值为0
counter1 = 1;
counter2 = 0;
最后得出咱们想要的结果。
SingletonTwo相同的方式来验证,不作赘述。