面试题:单例,还是单例
今天表弟问道一个面试题,结果票眼一看,尽然我回答错误了。值得深思:
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的顺序就显得格外重要,避免犯类似的错误。
上一篇: 010_swiftui_sf-symbols 系统资源
下一篇: mysql or和and有什么区别