3

问题说明了一切。有什么特殊事件发生吗?我有一个类需要实现 Serializable 接口。我正在使用 Wicket 开发应用程序。我已经实现了一个工厂类,它将提供一些链接(以消除重复写入的相同代码块的冗余):

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 框架的运行时环境引发的。如果我实施它,那么它就消失了。

ObjectInputStream#readobject()那么,当为单例模式创建的某个对象调用方法时,究竟会发生什么呢?

我没有添加检票口标签,因为我认为这个问题与检票口无关。

4

2 回答 2

5

不幸的是,默认情况下会发生第二个(或第三个,或第三十七个)单例实例——不好。幸运的是,有一种解决方法:通过实现readResolve()方法,该方法可以返回一个替换对象——在你的情况下是正确的单例对象——而不是默认序列化返回的那个。该链接描述了细节,但它非常简单——您只需实现此无参数实例方法即可返回单例对象。

于 2012-05-05T18:22:25.987 回答
3

实现序列化安全单例的另一种方法是使用枚举。请参阅此答案及其链接。简而言之,这个想法是 Java 已经保证在 JVM 中只有一个给定枚举值的实例,即使面对序列化也是如此,因此您可以将枚举值用作单例。这是一个黑客,但它是一个相当干净的黑客。

于 2012-05-05T19:04:08.350 回答