MST

星途 面试题库

面试题:Java单例模式的序列化与反序列化问题及解决

当一个实现了单例模式的类进行序列化和反序列化操作时,可能会破坏单例性。请阐述在Java中出现这种情况的原因,并给出至少两种解决方案来确保单例对象在序列化和反序列化后依然保持单例性。
16.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

原因

在Java中,当一个实现单例模式的类进行序列化和反序列化时,可能破坏单例性。这是因为ObjectInputStreamreadObject()方法在反序列化时,会创建一个新的对象实例,而不是使用已有的单例实例。即使单例类使用private构造函数来防止外部实例化,但反序列化机制可以绕过这个限制,从而创建多个实例,破坏单例性。

解决方案

  1. 使用readResolve方法

    import java.io.Serializable;
    
    public class Singleton implements Serializable {
        private static final long serialVersionUID = 1L;
        private static Singleton instance = new Singleton();
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            return instance;
        }
    
        protected Object readResolve() {
            return instance;
        }
    }
    

    当进行反序列化时,readResolve方法会被调用,它返回已有的单例实例,从而确保单例性。

  2. 使用枚举类型

    public enum SingletonEnum {
        INSTANCE;
    
        // 可以在这里添加其他业务方法
        public void doSomething() {
            System.out.println("Doing something in singleton.");
        }
    }
    

    枚举类型在Java中天然支持序列化和反序列化,并且JVM保证每个枚举常量在全局只有一个实例。所以使用枚举来实现单例模式可以避免在反序列化时创建新的实例,保证单例性。