2012-05-05 9 views
3

質問はすべてを言います。特別なイベントはありますか?私はSerializableインターフェイスを実装する必要があるクラスがあります。私はWicketを使ってアプリケーションを開発しています。である、java.io.ObjectOutputStream.writeObjectで私はSerializableを実装していない場合はシングルトンパターンでシリアライズ可能オブジェクトを作成するとどうなりますか?

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); 
      } 
     }; 
    } 
} 

その後、私は取得しています例外:私は(何度も書かれた同じコードブロックの冗長性を除去するため)いくつかのリンクを提供しますファクトリクラスを実装していますwicketフレームワークの実行時環境によってスローされます。私がそれを実装すると、それはなくなってしまいます。

したがって、シングルトンパターンによって作成されたオブジェクトに対してObjectInputStream#readobject()メソッドを呼び出すと、実際に何が起こりますか?

私はこの質問がWicketに関連しているとは思わないので、私はWicketタグを追加していません。

+1

getFactoryメソッドでは、synchronizedセクションは必要ありません。このシングルトンホルダーの目的(追加同期を避ける) – Anton

答えて

5

残念ながら、デフォルトでは、シングルトンの2番目(または3番目または37番目)のインスタンスが得られます。幸いなことに、これを回避する方法があります。readResolve()メソッドを実装することで、デフォルトの直列化によって返されたオブジェクトの代わりに、置換オブジェクト(適切なシングルトンオブジェクト)を返すことができます。このリンクでは詳細を説明していますが、シンプルですが、シングルトンオブジェクトを返すためにこのパラメータレスのインスタンスメソッドを実装するだけです。

+0

ありがとうございました。私は質問で与えられたクラスを更新しました。今は大丈夫ですか? –

+0

完璧に見える、はい。 –

+0

ありがとうございます。 "readResolveメソッドは、ObjectInputStreamがストリームからオブジェクトを読み込んだときに呼び出されます"というリンクに書かれていますが、この 'readResolve'メソッドが呼び出される人は誰もわかりません。 –

3

シリアル化セーフなシングルトンを実装する別の方法は、列挙型を使用することです。 this answerとそのリンクを参照してください。簡単に言うと、Javaは、シリアル化されていても、JVMに与えられたenum値のインスタンスが1つしかないことをJavaが保証しているので、enum値をシングルトンとして使用できます。ハックですが、かなりクリーンなハックです。

関連する問題