单例模式
饿汉式
类加载阶段被初始化就会创建实例。提前创建。
class Singleton implements Serializable{
private Singleton(){
System.out.println("private Singleton()");
}
private static final Singleton INSTANCE=new Singleton();
public static Singleon getInstance(){
return INSTANCE;
}
public static void otherMethod(){
System.out.println("otherMethod()");
}
}
破坏单例情况——反射
void reflection(Class<?> clazz){
//通过反射获取无参构造函数
Constructor<?> constructor=clazz.getDeclaredConstructor();
//有参构造Constructor<?> constructor=clazz.getDeclaredConstructor(String.class,int.class);
//设置私有构造方法也能使用
constructor.setAccessible(true);
System.out.println("反射创建实例:"+constructor.newInstance());
}
预防反射破坏单例——改造构造方法
private Singleton(){
if(INSTANCE !=null){
throw new RuntimeException("单例对象已经创建,不能重复创建");
}
System.out.println("private Singleton()");
}
破坏单例情况——反序列化
void serializable(Object instance){
ByteArrayOutputStream boStream=new ByteArrayOutputStream();
ObjectOutputStream ooStream=new ObjectOutputStream(boStream);
//把得到的对象变成字节流。
ooStream.writeObject(instance);
//字节流反序列化得到一个新的对象
ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(boStream.toByteArray()));
System.out.println("反序列化创建实例:"+ois.readObject());
}
预防反序列化破坏单例——添加特殊方法readResolve()
public Object readResolve(){
return INSTANCE;
}
破坏单例情况——Unsafe
void unsafe(Class<?> clazz){
Object o=UnsafeUtils.getUnsafe().allocateInstance(clazz);
System.out.println("Unsafe创建实例:"+o);
}
枚举饿汉式
预防 反射、反序列化破坏单例模式。
enum Singleton{
INSTANCE;
private Singleton(){}
System.out.println("private Singleton()");
}
public static Singleon getInstance(){
return INSRANCE;
}
public static void otherMethod(){
System.out.println("otherMethod()");
}
//重写toString方法
String toString(){return getClass().getName+"@"+Integer.toHecString(hashCode());}
}
//枚举编译后enum xxx--->class xxx extends Enum<xxx>
class Singleton extends Enum<Singleton>{
public static final Singleton INSTANCE;
//名字,序号0开始
private Singleton(String name,int ordinal){
super(name,ordinal);
}
//静态代码块,类加载时执行
static{
INSTANCE=new Singleton("INSTANCE",0);
}
}
破坏单例情况——Unsafe
void unsafe(Class<?> clazz){
Object o=UnsafeUtils.getUnsafe().allocateInstance(clazz);
System.out.println("Unsafe创建实例:"+o);
}
通过Unsafe造出一个Enum对象
public class CreateEnum {
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe= (Unsafe) unsafeField.get(null);
//获取字段偏移量(储存单元的实际地址与其所在的段地址之间的距离)
//objectFieldOffset获取非静态属性Field在对象实例中的偏移量
//staticFieldOffset获取静态属性Field在对象实例中的偏移量
long nameOffset = unsafe.objectFieldOffset(Enum.class.getDeclaredField("name"));
long ordinalOffset = unsafe.objectFieldOffset(Enum.class.getDeclaredField("ordinal"));
//用于创建一个类的实例,不会调用这个实例的构造方法
Sex o= (Sex) unsafe.allocateInstance(Sex.class);
//CAS 操作 给新对象赋值 (对象,字段偏移量,原始值,更新值)
unsafe.compareAndSwapObject(o,nameOffset,null,"犹太人");
unsafe.compareAndSwapInt(o,ordinalOffset,0,2);
System.out.println(o.name());
System.out.println(o.ordinal());
Sex o1=Sex.MAN;
System.out.println(o1.name());
System.out.println(o1.ordinal());
}
enum Sex{
MAN;
}
}
懒汉式DCL(Double Check Lock)
class Singleton implements Serializable{
private Singleton(){
System.out.println("private Singleton()");
}
//类加载时不创建对象
//volatile 保证可见性,有序性(避免指令重排导致 赋值操作提前 )
private static volatile Singleton INSTANCE=null;
//等调用时再创建对象
public static Singleon getInstance(){
if(INSTANCE==null){
synchronized (Singleton.class){
if(INSTANCE==null){
INSTANCE=new Singleton();
}
}
}
return INSTANCE;
}
public static void otherMethod(){
System.out.println("otherMethod()");
}
}
懒汉式——内部类
class Singleton implements Serializable{
private Singleton(){
System.out.println("private Singleton()");
}
//内部类
private static class Holder{
static Singleton INSTANCE=new Singleton();
}
//等调用时再创建对象
public static Singleon getInstance(){
return Holder.INSTANCE;
}
public static void otherMethod(){
System.out.println("otherMethod()");
}
}