单例在编程中经常使用,但在全局变量中应用会出现一些问题。
例子:
public class Tst {
public static void main(String[] args) {
A.getInstance();
}
}
class Glbl {
static {
System.out.println("In class GlblVars");
}
public static String log = "I love java.";
public static A a = A.getInstance();
}
class A {
static int instanceNum = 0;
private A() {
instanceNum ++;
int n = instanceNum;
System.out.println(n +" create instance A");
System.out.println(Glbl.log);
System.out.println(n +" create instance A done");
}
private static A instance;
public static A getInstance() {
if (instance == null) {
System.out.println("In class A");
instance = new A();
}
return instance;
}
}
运行结果 写道
In class A
1 create instance A
In class GlblVars
In class A
2 create instance A
I love java.
2 create instance A done
I love java.
1 create instance A done
1 create instance A
In class GlblVars
In class A
2 create instance A
I love java.
2 create instance A done
I love java.
1 create instance A done
类A生成了,两个对象,因为在调用【A.getInstance();】的时候,给A初始化,A的构造函数中又使用了全局变量【Glbl.log】,这样java虚拟机就会载入类Glbl,这样就会把里面的static的变量a初始化,就又生成了一个A对象了。
关键点就是A的构造函数又引用了有A静态变量的类。
消除这个问题:
1,去除Glbl 中的静态变量A。【推荐这种因为A.getInstance();这种访问本来就是全局的了,没必要在画蛇添足。】
2,使用Glbl.a来访问A的实例,而不是【A.getInstance();】。
看了《Java与模式》好像采用“饿汉式单例”同样可以解决这个问题:
public class Tst {
public static void main(String[] args) {
A.getInstance();
}
}
class Glbl {
static {
System.out.println("In class GlblVars");
}
public static String log = "I love java.";
public static A a = A.getInstance();
}
class A {
static {
System.out.println("In class A");
}
static int instanceNum = 0;
private A() {
instanceNum ++;
int n = instanceNum;
System.out.println(n +" create instance A");
System.out.println(Glbl.log);
System.out.println(n +" create instance A done");
}
private static A instance = new A();
public static A getInstance() { return instance;}
}
结果:
In class A
1 create instance A
In class GlblVars
I love java.
1 create instance A done