Java静态变量以及非标准单态模式的坑

来源:互联网 发布:踏浪100网站源码 编辑:程序博客网 时间:2024/06/05 09:20

今天遇到一个很诡异的bug,调试了半天也没有看出来有什么问题,抽象一下代码如下:

结果一运行就出下面的错误,

java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
 at edu.bupt.test.Instance.<init>(Instance.java:27)
 at edu.bupt.test.Instance.<clinit>(Instance.java:9)
Exception in thread "main"

 

当时没有太注意这个Exception,因为还有另外一个NullException

后来仔细看了一下堆栈才发现,这是在初始化的过程中出的问题,

首先我们来回忆一下类的加载过程

1、加载类文件

2、初载父类

3、初始化静态变量和static代码块

4、调用构造函数

 

好了,问题就出在第3步了,因为这里我们用了一个非标准的单态模式,

直接把静态变量在static里初始化了。由于第三步的初始化步骤是根据你

的变量的定义顺序来初始化的,于是杯具产生了:

首先,你要初始化static Instance instance,这样你就要调用Instance

的构造函数,这个时候,构造函数里要访问map变量,而这个static变量

还没有初始化呢,于是空指针就出现了。

 

结论:要仔细阅读栈的话,这个问题还是很容易定位的,这么看init代表构造函数

而cinit代表静态初始化函数,因此这个过程其实是在静态初始化调用构造函数时

发生的,去看一个构造函数分析一下就得到结果了。

 

另外尽可能避免地使用在变量定义时就初始化变量,这样会导致一些问题的追查

比较麻烦,比如这个问题就是一个很典型的例子,解决问题的办法居然是要将两个

变量定义顺序调整一下,如果使用了一些代码format工具,比如eclipse的format功能,

这种诡异的bug就会出现了。

原创粉丝点击