Effective Java 輪読会 
2014/03/19 
開発部田中
項目77 
インスタンス制御に対しては、readResolve 
よりenum 型を選ぶ
readResolveによるインスタンス制御 
• シングルトンをシリアライズする場合の伝 
統的な方法 
o 自身の持つシングルトンインスタンスを返すような 
readResolveメソッドを定義することで、デシリア 
ライズによって生成されたインスタンスは破棄し、 
常にメモリ上に存在するインスタンスの参照を返す。
インスタンス制御する場合のtransient 
• readResolveによって常にメモリ上のインス 
タンスを返すのなら、シングルトンクラス 
のインスタンスフィールドをシリアライズ 
の対象にする必要はない。 
→ transient修飾子を付与する
攻撃に備えてtransientを付与する 
• むしろreadResolveによってシリアライズさ 
れるクラスのインスタンスフィールドは 
transientにすべき 
• readResolveが呼ばれる前に、デシリアライ 
ズによって生成されたインスタンスの参照 
を「盗む」ことができてしまう。
実際に参照を盗んでみる
enumを使う 
• readResolveによるインスタンス制御は、廃 
れてはいないが、十分な注意が必要 
• そこで、enumを使えば、シングルトン特性 
をJVMが保証してくれる 
• enumが使えない場合もある
readResolveのアクセス可能性 
• デシリアライズは、クラス階層の上から行 
われる。 
• スーパークラスのインスタンスが生成され 
てClassCastExceptionが発生しないように 
気をつける
まとめ 
• シリアライズのインスタンス制御には、可 
能な限りenumを使う 
• readResolveメソッドによるインスタンス制 
御の場合は、インスタンスフィールドがプ 
リミティブ型か、transientであることを確認 
する
項目78 
シリアライズされたインスタンスの代わりに、 
シリアライズ・プロキシを検討する 
・シリアライズ・プロキシ・パターンとは 
・writeReplace とreadResolve
なぜ使うか 
• ネストしたクラスに、エンクロージングク 
ラスの論理的状態を表現する 
• シリアライズ・プロキシから元のクラスの 
インスタンスに復元する際に、元のクラス 
のコンストラクタを使用できる 
• 言語機能によってデシリアライズを制御できる
ポイント1: writeReplace 
• エンクロージングクラスをシリアライズ・ 
プロキシへ変換する(シリアライズ・プロ 
キシクラスの形式でシリアライズする)
ポイント2: readResolve 
• シリアライズ・プロキシクラスに 
readResolveを実装する 
• デシリアライズの際にシリアライズ・プロ 
キシをエンクロージングクラスのインスタ 
ンスにエンクロージングクラスのコンスタ 
ラクタを使って変換する。
readResolveの柔軟性 
• readResolveではpublicのAPIのみを使用して 
インスタンスを生成できる 
• staticファクトリーメソッドも使える 
• 実際にどのクラスのインスタンスを返すか 
制御できる。 
• ex. EnumSet
まとめ 
• finalクラスについて、readObjectや 
writeObjectを書く必要がある場合には、シ 
リアライズ・プロキシ・パターンを検討す 
る 
• クラスの不変式をシリアライズするための 
簡単・確実な方法

Effective Java 輪読会 項目77-78