技术学习笔记
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode

6.2其他方法实现单例模式

静态内部类实现单例

MyObject.java
public class MyObject {
    private static class MyObjectHandler{
        private static MyObject myObject = new MyObject();
    } 
    private MyObject(){}
    public static MyObject getInstance(){
        return MyObjectHandler.myObject;
    }
}

序列化与反序列化的单例模式

静态实现的单例对象,在序列化和反序列化时会出现违背单例的情况。

解决方法是,在单例类定义中添加 readResolve 代码段:

//静态属性 
protected Object readResolve(){
        System.out.println("调用了 readResolve");
        return MyObject.myObject;
    }

//静态内部类
protected Object readResolve(){
        System.out.println("调用了 readResolve");
        return MyObjectHandler.myObject;
    }
MyObject.java
import java.io.Serializable;

public class MyObject implements Serializable {
    private static class MyObjectHandler{
        private static MyObject myObject = new MyObject();
    }
    private MyObject(){}
    public static MyObject getInstance(){
        return MyObjectHandler.myObject;
    }
}

Run.java
public class Run {
    public static void main(String[] args) {
        try {
            MyObject myObject = MyObject.getInstance();
            FileOutputStream fos = new FileOutputStream(new File("a.txt"));
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(myObject);
            System.out.println(myObject.hashCode());
            oos.close();
            fos.close();
        }catch (IOException e){

        }

        try{
            FileInputStream fis = new FileInputStream(new File("a.txt"));
            ObjectInputStream ois = new ObjectInputStream(fis);
            MyObject myObject = (MyObject) ois.readObject();
            System.out.println(myObject.hashCode());
            ois.close();
            fis.close();
        }catch (IOException e ){

        }catch (ClassNotFoundException e){

        }
    }
}

运行结果

1267032364
1598924227

使用的是静态内部类实现单例模式,但序列化写对象和反序列化读对象得到的却不是同一个,违背单例模式。

解决方法:修改 MyObject.java
import java.io.Serializable;

public class MyObject implements Serializable {
    private static class MyObjectHandler{
        private static MyObject myObject = new MyObject();
    }
    private MyObject(){}
    public static MyObject getInstance(){
        return MyObjectHandler.myObject;
    }

    protected Object readResolve(){
        System.out.println("调用了 readResolve");
        return MyObjectHandler.myObject;
    }
}

修改之后运行结果显示,序列化对象和反序列化得到的对象是同一个对象。

1267032364
调用了 readResolve
1267032364


static 代码块实现单例

实质上,静态块的实现原理与静态属性相同,即

 private static MyObject myObject = null;
 static {
        myObject = new MyObject();
    }

相当于

 private static MyObject myObject = new MyObject();

静态块实现单例
import java.io.Serializable;

public class MyObject implements Serializable {
    private static MyObject myObject = null;
    static {
        myObject = new MyObject();
    }

    private MyObject(){}
    public static MyObject getInstance(){
        return MyObject.myObject;
    }
    //用于解决反序列化问题
    protected Object readResolve(){
        System.out.println("调用了 readResolve");
        return MyObject.myObject;
    }
}

enum 实现单例

这种方式实现单例,序列化的对象和反序列化得到的对象是同一个对象。

MyObject.java
import java.io.Serializable;

public class MyObject implements Serializable {
    public enum MyEnumSingleton {
        stringFactory;
        private String string = new String("Fine");
        public String get(){
            return string;
        }
    };
    public static String get(){
        return MyEnumSingleton.stringFactory.get();
    }
}

MyThread.java
public class MyThread extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 5; i++) {
            System.out.println(MyObject.get().hashCode());
        }
    }
}
Run.java
public class Run {
    public static void main(String[] args) {
        MyThread A = new MyThread();
        MyThread B = new MyThread();
        MyThread C = new MyThread();

        A.start();
        B.start();
        C.start();
    }
}