问题说明了一切。有没有特别的事件发生?我有一个需要实现Serializable接口的类。我正在使用Wicket开发一个应用程序。我已经实现了一个Factory类,它将提供一些链接(删除反复写入的相同代码块的冗余):
public class NavigationLinkFactory implements Serializable {
private static final long serialVersionUID = 7836960726965363785L;
private NavigationLinkFactory() {
}
private static class SingletonHolder {
public static final NavigationLinkFactory instance = new NavigationLinkFactory();
}
public static NavigationLinkFactory getFactory() {
return SingletonHolder.instance;
}
private Object readResolve() throws ObjectStreamException {
return SingletonHolder.instance;
}
public Link<Serializable> getUserHomeLink() {
return new Link<Serializable>("home", new Model<Serializable>()) {
private static final long serialVersionUID = -8282608926361995521L;
@Override
public void onClick() {
EMSSession session = (EMSSession) getSession();
session.setActiveHorizonalMenu(1);
setResponsePage(HomePage.class);
}
};
}
public Link<Serializable> getProfileLink() {
return getProfileViewLink();
}
public Link<Serializable> getProfileViewLink() {
return new Link<Serializable>("profileView", new Model<Serializable>()) {
private static final long serialVersionUID = 232185489384306999L;
@Override
public void onClick() {
EMSSession session = (EMSSession) getSession();
session.setActiveHorizonalMenu(2);
setResponsePage(ProfileViewPage.class);
}
};
}
}
如果我没有实现Serializable,那么我在java.io.ObjectOutputStream.writeObject
获得异常,这是由wicket框架的运行时环境抛出的。如果我实施它然后它就消失了。
那么当为Singleton模式创建的某个对象调用ObjectInputStream#readobject()
方法时会发生什么?
我没有添加wicket标签,因为我不认为这个问题与Wicket有关。
答案 0 :(得分:5)
不幸的是,默认情况下你会得到你的单身的第二个(或第三个,或第三十七个)实例 - 不好。幸运的是,有一种解决方法:通过实现readResolve()方法,它可以返回一个替换对象 - 在你的情况下是正确的单例对象 - 而不是默认序列化返回的对象。该链接描述了详细信息,但它非常简单 - 您只需实现此无参数实例方法即可返回单例对象。
答案 1 :(得分:3)
实现序列化安全单例的另一种方法是使用枚举。请参阅this answer及其中的链接。简而言之,这个想法是Java已经保证JVM中只有一个给定枚举值的实例,即使面对序列化,所以你可以使用枚举值作为单例。这是一个黑客,但它是一个相当干净的黑客。