欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面试题:单例,还是单例

程序员文章站 2022-03-06 18:00:46
...

今天表弟问道一个面试题,结果票眼一看,尽然我回答错误了。值得深思:

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的顺序就显得格外重要,避免犯类似的错误。

相关标签: 面试