15
Effective Java 輪輪輪 2014/03/19 開開開 開開

Effective Java 輪読会 項目77-78

Embed Size (px)

Citation preview

Page 1: Effective Java 輪読会 項目77-78

Effective Java 輪読会2014/03/19

 開発部 田中

Page 2: Effective Java 輪読会 項目77-78

項目 77

 インスタンス制御に対しては、 readResolve  より enum 型を選ぶ

Page 3: Effective Java 輪読会 項目77-78

readResolveによるインスタンス制御

• シングルトンをシリアライズする場合の伝統的な方法o 自身の持つシングルトンインスタンスを返すような readResolveメソッドを定義することで、デシリアライズによって生成されたインスタンスは破棄し、常にメモリ上に存在するインスタンスの参照を返す。

Page 4: Effective Java 輪読会 項目77-78

インスタンス制御する場合のtransient

• readResolveによって常にメモリ上のインスタンスを返すのなら、シングルトンクラスのインスタンスフィールドをシリアライズの対象にする必要はない。→ transient修飾子を付与する

Page 5: Effective Java 輪読会 項目77-78

攻撃に備えて transientを付与する

• むしろ readResolveによってシリアライズされるクラスのインスタンスフィールドはtransientにすべき

• readResolveが呼ばれる前に、デシリアライズによって生成されたインスタンスの参照を「盗む」ことができてしまう。

Page 6: Effective Java 輪読会 項目77-78

実際に参照を盗んでみる

Page 7: Effective Java 輪読会 項目77-78

enumを使う

• readResolveによるインスタンス制御は、廃れてはいないが、十分な注意が必要

• そこで、 enumを使えば、シングルトン特性を JVMが保証してくれる

• enumが使えない場合もある

Page 8: Effective Java 輪読会 項目77-78

readResolveのアクセス可能性

• デシリアライズは、クラス階層の上から行われる。

• スーパークラスのインスタンスが生成されて ClassCastExceptionが発生しないように気をつける

Page 9: Effective Java 輪読会 項目77-78

まとめ

• シリアライズのインスタンス制御には、可能な限り enumを使う

• readResolveメソッドによるインスタンス制御の場合は、インスタンスフィールドがプリミティブ型か、 transientであることを確認する

Page 10: Effective Java 輪読会 項目77-78

項目 78

シリアライズされたインスタンスの代わりに、シリアライズ・プロキシを検討する

・シリアライズ・プロキシ・パターンとは・ writeReplace  と readResolve

Page 11: Effective Java 輪読会 項目77-78

なぜ使うか

• ネストしたクラスに、エンクロージングクラスの論理的状態を表現する

• シリアライズ・プロキシから元のクラスのインスタンスに復元する際に、元のクラスのコンストラクタを使用できる• 言語機能によってデシリアライズを制御できる

Page 12: Effective Java 輪読会 項目77-78

ポイント 1: writeReplace

• エンクロージングクラスをシリアライズ・プロキシへ変換する(シリアライズ・プロキシクラスの形式でシリアライズする)

Page 13: Effective Java 輪読会 項目77-78

ポイント 2: readResolve

• シリアライズ・プロキシクラスにreadResolveを実装する

• デシリアライズの際にシリアライズ・プロキシをエンクロージングクラスのインスタンスにエンクロージングクラスのコンスタラクタを使って変換する。

Page 14: Effective Java 輪読会 項目77-78

readResolveの柔軟性

• readResolveでは publicの APIのみを使用してインスタンスを生成できる

• staticファクトリーメソッドも使える

• 実際にどのクラスのインスタンスを返すか制御できる。• ex. EnumSet

Page 15: Effective Java 輪読会 項目77-78

まとめ

• finalクラスについて、 readObjectやwriteObjectを書く必要がある場合には、シリアライズ・プロキシ・パターンを検討する

• クラスの不変式をシリアライズするための簡単・確実な方法