目前单例模式有三种形式
1、提供一个静态的公共属性
2、提供一个静态的公共方法
3、enum类型的(这个是针对jdk 1.5以及1.5版本以上的)
enum SingletonExample {
INSTANCE;
public static SingletonExample getInstance() {
return INSTANCE;
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class EnumTest {
public static void singletonTest() throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException {
try {
//得到第一个实例
SingletonExample s = SingletonExample.getInstance();
//用反射得到第二个实例,这里引用类的时候得写全路径,否则会报找不到类
Class c = Class.forName("com.wush.singleton.SingletonExample");
//getDeclaredConstructors返回 Constructor 对象的一个数组,
//这些对象反映此 Class 对象表示的类声明的所有构造方法。
//它们是公共、保护、默认(包)访问和私有构造方法。
//返回数组中的元素没有排序,也没有任何特定的顺序。
//如果该类存在一个默认构造方法,则它包含在返回的数组中。
//如果此 Class 对象表示一个接口、一个基本类型、一个数组类或 void,
//则此方法返回一个长度为 0 的数组
Constructor[] con = c.getDeclaredConstructors();
Constructor conc = con[0];
//setAccessible将此对象的 accessible 标志设置为指示的布尔值。
//值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
//值为 false 则指示反射的对象应该实施 Java 语言访问检查。
conc.setAccessible(true);
SingletonExample ss = (SingletonExample)conc.newInstance();
System.out.println(s+"/"+ss);
System.out.println(s==ss);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IllegalArgumentException,
InstantiationException, IllegalAccessException, InvocationTargetException {
singletonTest();
}
}
结果如下
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:492)
at com.test.EnumTest.singletonTest(EnumTest.java:26)
at com.test.EnumTest.main(EnumTest.java:34)
从结果可以看出用enum的单例是最安全的,其它两种方式都可以用反射得到