面试题答案
一键面试原因
在Java中,当一个实现单例模式的类进行序列化和反序列化时,可能破坏单例性。这是因为ObjectInputStream
的readObject()
方法在反序列化时,会创建一个新的对象实例,而不是使用已有的单例实例。即使单例类使用private
构造函数来防止外部实例化,但反序列化机制可以绕过这个限制,从而创建多个实例,破坏单例性。
解决方案
-
使用
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
方法会被调用,它返回已有的单例实例,从而确保单例性。 -
使用枚举类型
public enum SingletonEnum { INSTANCE; // 可以在这里添加其他业务方法 public void doSomething() { System.out.println("Doing something in singleton."); } }
枚举类型在Java中天然支持序列化和反序列化,并且JVM保证每个枚举常量在全局只有一个实例。所以使用枚举来实现单例模式可以避免在反序列化时创建新的实例,保证单例性。