简介
说明
本文介绍Java破坏单例模式的方法。
单例模式(Singleton Pattern)是指确保一个类只有一个实例,并提供一个全局访问点。破坏单例模式的话,就是说可以创建出两个或两个以上的实例。本文通过静态内部类方式进行说明。
破坏单例的方法
破坏单列模式的方式
- 反射
- 序列和反序列化
- 使用不同的类加载器
上边1, 2都可以用枚举来解决,具体见:此文。
反射
破坏单例模式
单例类
package org.example.a; public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
测试类
package org.example.a; import java.lang.reflect.Constructor; public class Demo { public static void main(String[] args) { Class<?> singletonClass = Singleton.class; try { Constructor c = singletonClass.getDeclaredConstructor(null); c.setAccessible(true); Object singleton1 = c.newInstance(); Object singleton2 = c.newInstance(); System.out.println(singleton1 == singleton2); } catch (Throwable e) { e.printStackTrace(); } } }
执行结果(创建出了两个不同的实例)
false
防止反射破坏单例模式
在构造函数里防止反射。
单例类
package org.example.a; public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() { if (SingletonHolder.INSTANCE != null) { throw new RuntimeException("不允许通过反射创建实例"); } } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
测试类(通过反射获得实例)
package org.example.a; import java.lang.reflect.Constructor; public class Demo { public static void main(String[] args) { Class<?> singletonClass = Singleton.class; try { Constructor c = singletonClass.getDeclaredConstructor(null); c.setAccessible(true); Object singleton1 = c.newInstance(); System.out.println("singleton1 instance create successfully"); Object singleton2 = c.newInstance(); System.out.println("singleton2 instance create successfully"); System.out.println(singleton1 == singleton2); } catch (Throwable e) { e.printStackTrace(); } } }
执行结果
Caused by: java.lang.RuntimeException: 不允许通过反射创建实例
测试类(通过静态方法获得实例)
package org.example.a; public class Demo { public static void main(String[] args) { Singleton singleton = Singleton.getInstance(); System.out.println("singleton create successfully"); } }
执行结果
singleton create successfully
防止反射破坏单例模式的原理
1.用getInstance
调用到new Singleton()时,此时INSTANCE是null,所以不会报错。
2.用反射
调用构造方法时,调用到Singleton.INSTANCE,然后会再new Singleton()赋值给Singleton.INSTANCE,此时,Singleton.INSTANCE不为null。
序列化与反序列化
此内容仅限VIP查看,请先登录
请先
!