面试题:单例,还是单例
今天表弟问道一个面试题,结果票眼一看,尽然我回答错误了。值得深思:
package com.io.test;class Singleton {private static Singleton singleton = new Singleton();public static int counter1;public static int counter2 = 0;private Singleton() {counter1++;counter2++;}public static Singleton getInstance() {return singleton;}}public class IoDemo01 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println("counter1:" + singleton.counter1);System.out.println("counter2:" + singleton.counter2);}}?
?
答案是:1和0
?
为什么?其实很简单,因为static初始化是线性的。
1. 静态变量singleton导致new Singleton
2. Singleton构造函数导致counter1,counter2都变成1了
3. public static int counter2 = 0; 初始化又变为0了.
?
所以结果就变成了输出:counter1:1????? counter2:0
可能有人就要问了,为什么public static int counter1;不会变成再此初始化为0?
其实这就是关键所在。所有的引用类型的静态变量默认为null, 数值为0,bool为false,这些都是发生在静态初始化之前的. 这也是为什么在构造函数中还未执行到初始化counter1时,他++就等于1的原因,而不是一个乱序的数字.
?
?
通过javap这些初始化也是看不见的,除非像count2 = 0那样手动赋值的情况。下面是通过查看javap的一段过程
?
?
1.IoDemo这个类导致Singleton加载.
?
?
2.Singleton的clinit调用
?
3. 看见上面init了吧,构造函数开始调用:分别给counter1++, counter2++

?
4. 上面return后就回到图1, 再把counter2设置为0.

?
?
这也是为什么结果1和0了。
?
?
?
实际上扯了这么多也和单例没半毛钱关系,但是现在单例一般都写成这种方式,所以有时想初始化一些东西时,static的顺序就显得格外重要,避免犯类似的错误。