美文网首页
Java 序列化 之 单例模式

Java 序列化 之 单例模式

作者: 4553675200ad | 来源:发表于2019-05-17 21:04 被阅读0次

    当我们使用Singleton模式时,应该是期望某个类的实例应该是唯一的,但如果该类是可序列化的,那么发序列化后还会是单例的吗?下面我们通过如下示例一来验证一下:

    示例一

    User 类

    User 类是单例模式,使用的饿汉模式,在类加载的时候就创建对象实例。

    public class User implements Serializable {
        private static final long serialVersionUID = 3380014540967816490L;
    
        private String userName;
        private String password;
    
        private static User user = new User("zhangsan", "test");
    
        private User(String userName, String password) {
            this.userName = userName;
            this.password = password;
        }
        public static User getInstance() {
            return user;
        }
        public String getUserName() {
            return userName;
        }
        public String getPassword() {
            return password;
        }
    
    

    Test 类

    测试类,把 User 的单例实例序列化后在反序列化

    public class Test{
        public static void main(String[] args) throws Exception {
            File file = new File("d:\\a.user");
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(User.getInstance());
    
    
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            User user = (User) ois.readObject();
            System.out.println(user);
    
            if(user==User.getInstance()){
                System.out.println("同一个实例");
            }else{
                System.out.println("不同的实例");
            }
        }
    }
    
    

    执行结果如下:

    输出的结果:
    User [userName=zhangsan, password=123456]
    不同的实例

    通过结果可以看出,单例模式的饿汉模式也无法确保对象实例是单例的。

    那么我们应该怎么解决这个问题呢?

    readResolve() 方法

    public class User implements Serializable {
    
        private static final long serialVersionUID = 3380014540967816490L;
    
        private String userName;
        private String password;
    
        private static User user = new User("zhangsan", "123456");
    
        private User(String userName, String password) {
            this.userName = userName;
            this.password = password;
        }
        public static User getInstance() {
            return user;
        }
        public String getUserName() {
            return userName;
        }
        public String getPassword() {
            return password;
        }
        public Object readResolve(){
            return getInstance();
        }
        @Override
        public String toString() {
            return "User [userName=" + userName + ", password=" + password + "]";
        }
    }
    

    我们在 User 类中添加了一个 readResolve() 方法,该方法直接返回单例中的示例。
    然后在执行 Test.main() 方法
    执行结果如下:

    输出的结果:
    User [userName=zhangsan, password=123456]
    相同的实例

    无论是实现Serializable接口,或是Externalizable接口,当从I/O流中读取对象时,readResolve()方法都会被调用到。实际上就是用readResolve()中返回的对象直接替换在反序列化过程中创建的对象。

    相关文章

      网友评论

          本文标题:Java 序列化 之 单例模式

          本文链接:https://www.haomeiwen.com/subject/rhuzoqtx.html