Java 单例模式一般有两种实现:
1.暴露静态final字段
- public class Elvis {
- public static final Elvis INSTANCE = new Elvis();
- private Elvis(){;;;}
- public void leaveTheBuilding() {;;;}
- }
2.暴露静态方法
- public class Elvis {
- private static final Elvis INSTANCE = new Elvis();
- private Elvis(){;;;}
- public static Elvis getInstance() { return INSTANCE;}
- public void leaveTheBuilding() {;;;}
- }
如果借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器,抵御这种方法可以在创建第二次构造器时抛出异常来解决。
自定义异常:
- public class InitializationException extends RuntimeException {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- public InitializationException(String msg) {
- super(msg);
- }
- }
单例类:
- public class Singleton {
- private static int count = 0;
- private static final Singleton INSTANCE = new Singleton();
- private Singleton() {
- if(count == 1)
- throw new InitializationException("只能初始化一次!");
- count++;
- }
- public static Singleton getInstance() {
- return INSTANCE;
- }
- }
测试类:
- public class Test {
- public static void main(String[] args) throws Exception{
- Singleton s1 = Singleton.getInstance();
- Singleton s2 = Singleton.getInstance();
- System.out.println(s1 == s2); // 返回 true
- // 试图通过反射机制创建实例
- for(Constructor<?> c : s1.getClass().getDeclaredConstructors()) {
- c.setAccessible(true); // AccessibleObject
- Singleton s3 = (Singleton)c.newInstance();
- }
- }
- }
抛出的异常:
- Exception in thread "main" java.lang.reflect.InvocationTargetException
- at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
- at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
- at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
- at java.lang.reflect.Constructor.newInstance(Unknown Source)
- at org.reflect.Test.main(Test.java:17)
- Caused by: org.reflect.InitializationException: 只能初始化一次!
- at org.reflect.Singleton.<init>(Singleton.java:10)
- ... 5 more
原文:http://blog.youkuaiyun.com/czjuttsw/article/details/8514989