SlideShare a Scribd company logo
1 of 20
Effective Java 輪読会 
Item 74-75 
開発部陳映融2014/3/12
第11章シリアライズ 
 項目74 Serializable を注意して実装する 
 項目75 カスタムシリアライズ形式の使用を検討する 
 項目76 防御的にreadObject を書く 
 項目77 インスタンス制御に対しては、readResolve よりenum 型を選 
ぶ 
 項目78 シリアライズされたインスタンスの代わりに、シリアライズ・プロキ 
シを検討する 
※ スペースの関係で、以下では一部の「シリアライズ」を「直列化」として表記 
2
Item 74 
Serializable を注意して実装する
Serializable を実装すること 
 クラスのインスタンスをシリアライズ可能にすること 
4 
 誤解:シリアライズ可能にするのは簡単で、大した努力はいらない 
 「クラス宣言にimplements Serializable を追加するだけでできる」 
⇒ 簡単にできるけど、長期的なスパンではひどい目にあうことに... 
 Serializable を実装する際の主要コスト 
 一旦リリースされるとクラスの実装を変更する柔軟性が低下 
 バグやセキュリティホールの可能性が増大 
 新しいバージョンのクラスをリリースすることに関連するテストの負荷が増大 
⇒ Serializable インタフェースの実装は軽く考えて決めることではない!
クラスの実装変更柔軟性への影響 
 シリアライズ可能=シリアライズ形式を公開API に含める 
5 
 デフォルトだとシリアライズ形式は最初の内部表現に結びつける 
 パッケージプライベートとprivate のインスタンスフィールドも公開API に 
⇒ フィールドへのアクセスを最小限にする実践(項目13)が無駄になる 
⇒ 長期間付き合える高品質のシリアライズ形式を注意深く設計すべき(項目75,78) 
 シリアライズ可能性に伴う発展に対する制約の例 
 シリアルバージョンUID(ストリーム一意識別子) 
 明示的指定しなければ、自動生成される値が適用される 
 自動生成される値は実装のインタフェースやメンバからの影響を受ける 
 クラスの実装を変更するとその値が変更される 
⇒ 明示的な宣言がないと互換性を失い、実行時にInvalidClassException
バグやセキュリティホールの可能性 
 シリアライズ=オブジェクト生成に関する言語外の仕組み 
6 
 ディシリアライズ=隠れたコンストラクタ 
 ディシリアライズの(コンストラクタとしての)責任 
 本当のコンストラクタにより確立された不変式を保証しなければならない 
 生成中オブジェクト内部へのアクセスをガードしなければならない 
 デフォルトのディシリアライズの仕組みへの依存 
⇒ オブジェクトを不変式破壊と不正アクセスのリスクに晒すこと
リリースに関連するテストの負荷 
 クラス互換性を維持するためのテストの組み合わせ 
7 
 新しいリリースでシリアライズ⇒ 今までの古いリリースでディシリアライズ 
 今までの古いリリースでシリアライズ⇒ 新しいリリースでディシリアライズ 
⇒ リリース数が増えると大変なことに... 
 互換性テストの内容 
 バイナリ互換性:バイナリ形式の互換性 
 セマンティック互換性:オブジェクトの意味の互換性 
⇒ 自動化での構築ができない 
 互換性テストの必要性 
 変更量に依存、変更量が大きいほど、テストの必要性が増大 
 注意深く設計されたカスタムシリアライズ形式ではテスト必要性は減る
Serializable を実装すべきか 
 クラスを実装するごとに、コストと恩恵を評価する 
 シリアライズに依存したフレームワークでクラスが使用される場合 
8 
 例えばオブジェクトの転送や永続化に関するフレームワーク 
⇒ Serializable を実装することは必要 
 Serializable を実装必須の他のクラスのコンポーネントとして 
⇒ Serializable を実装すると、クラスの使用を容易にする 
 一般則として 
 コレクションクラスや値クラスはSerializable を実装すべき 
 活動的な実体を表すクラスはSerializable をめったに実装すべきでない
Serializable を実装すべきか 
 継承のために設計されたクラス(インタフェースも基本的に同じ) 
9 
⇒ Serializable をめったに実装すべきでない 
 例外として、シリアライズに依存するフレームワークを使用する場合 
 内部クラス 
 クラス定義との対応が定義されず、デフォルトのシリアライズ形式は不明確 
 無名クラスやローカルクラスの名前 
 コンパイラ生成による人工的フィールド 
 エンクロージングインスタンス参照を保存用 
 外部スコープからローカル変数値を保存用 
⇒ Serializable を実装すべきではない 
 ただしstatic のメンバークラスはSerializable 実装できる
継承のために設計されたクラス 
 Serializable を実装するケース 
 シリアライズ可能かつ拡張可能で、 
10 
インスタンスフィールドを持つクラスを実装する際の注意事項 
 インスタンスフィールドがデフォルト値に初期化されると成り立たない不変式あるか? 
 クラスにそのような不変式がある場合は以下メソッドを追加 
// 状態を持ち拡張可能・シリアライズ可能クラスに対するreadObjectNoData を追加 
private void readObjectNoData() throws InvalidObjectException { 
throw new InvalidObjectException(“Stream data required”); 
 【要確認】サブクラスインスタンスのディシリアライズ処理において、ディシリアライズし 
ようとするオブジェクトが自クラスをスーパークラスとして列挙していない場合、フィール 
ドを適切な値に設定するためにreadObjectNoData は呼び出される 
 要するに、バージョンの違うサブクラスのオブジェクトをディシリアライズする状況 
 【Java オブジェクト直列化仕様】3.5 readObjectNoData メソッド 
 【stackoverflow】Java: When to add readObjectNoData() during 
serialization? 
}
継承のために設計されたクラス 
 Serializable を実装しないケース 
 パラメータなしコンストラクタの提供を検討する 
11 
⇒ サブクラスのシリアライズ可能の拡張性を残すように 
 不変式がすべて確立されるオブジェクトを生成するのが最善 
 不変式の確立にクライアントの情報提供が必要な場合は要注意 
public abstract class AbstractFoo { 
... 
// オブジェクトの完全性を意識して、アトミック参照で初期化状態を管理 
private final AtomicReference<State> init = new AtomicReference<>(State.NEW); 
protected AbstractFoo(int x, int y) { initialize(x, y); } 
// オブジェクトの生成手段のみ提供、別途初期化メソッドの呼び出しが必要 
protected AbstractFoo() {} 
// 未初期化時の初期化メソッド 
protect final void initialize(int x, int y) { ... } 
// 内部状態の正しさを保証する 
private void checkInit() { ... } 
... 
}
まとめ 
 Serializable の実装の容易さは見かけ倒し 
 短期間の使い捨てのクラスでなければ、Serializable を実装するか 
は真剣に決めるべき 
 Serializable を実装するかを決める場合、特に継承のために設計さ 
れたクラスは注意を払うべき 
 サブクラスでSerializable を実装・禁止することの中間的な設計ポイント 
12 
は、アクセス可能なパラメタなしコンストラクタを提供 
⇒ サブクラスがSerializable を実装することを許すが、強制はしない
Item 75 
カスタムシリアライズ形式の使用を検討する
デフォルト直列化形式の受け入れ 
 時間制約がある中でクラスを作成する場合、適切な方法として 
 最善のAPI 設計に努力を集中すべき 
 使い捨てのクラスで実装して、後のリリースで置き換える 
⇒ シリアライズ可能なクラスのシリアライズ形式はあとのリリースにも影響 
14 
(特にデフォルトのシリアライズ形式) 
 デフォルトのシリアライズ形式を受け入れる? 
 受け入れる前に、適切かどうかを最初に検討しなくてはならない 
 判断基準:オブジェクトの論理表現として適切か 
 デフォルトのシリアライズ形式はオブジェクトの物理表現を符号化したもの 
 論理表現と物理表現が同じであれば、おそらく適切 
 適切であると判断したら 
 不変式やとセキュリティを保証するため、多くの場合はreadObject メソッドを提 
供しなければならない
適切でないデフォルト直列化形式の使用 
 デフォルト直列化形式の使用が適切でない例 
 StringList (p.286) 
15 
 論理データ:文字列の列 
 物理表現:リンクリスト 
 適切でないデフォルトのシリアライズ形式の使用のデメリット 
 公開APIが現在の内部表現に永久拘束される 
 内部の実装が変わっても古い実装に関するコードは取り除くことできない 
 過剰な空間を消費する可能性がある 
 データを使いやすくするための仕組みの構造をシリアライズする価値はない 
 過剰な時間を消費する可能性がある 
 実装によってコストの高い検索を行うことになる場合も 
 スタックオーバーフローを起こす可能性がある 
 クラスの構造によって再帰的な検索がスタックオーバーフローを起こすかも
適切な直列化形式を持つクラスの実装 
 実装例: StringList (p.286) 
 シリアライズ形式:リスト内の文字列数と、文字列自身 
16 
 物理表現の詳細は取り除かれる 
 transient 修飾子でインスタントフィールドを標記 
 defaultWriteObject/defaultReadObject メソッドの呼び出し 
 すべてのインスタントフィールドがtransient ならば、技術的には呼び出し 
を省くことは許されるが、推奨しない 
 後方互換性と前方互換性を保ちながら、あとのリリースでtransient でない 
フィールドを追加可能
transient 識別子の使用 
 インスタントフィールドがデフォルト直列化形式から省かれることを示す 
 フィールドをtransient でないと決める前に、そのフィールドの値が、 
オブジェクトの論理状態の一部であることを確認するべき 
 デフォルト直列化形式を使用した場合、transient と宣言したフィールド 
はデフォルト値に初期化される 
 デフォルト値がそのフィールドに対して受け入れられない場合の対処 
17 
 受け入れられる値を回復させるreadObject メソッドを提供(項目76) 
 そのフィールドが最初に使用される時に遅延初期化を行う(項目71)
シリアライズ形式と関係ない注意事項 
 オブジェクト全体の状態を読み出す他のメソッドに課す同期をオブジェクト 
のシリアライズにも課さなければならない 
 例えば、すべてのメソッドを同期することでスレッド安全性を達成しているスレッ 
18 
ドセーフのオブジェクトで、デフォルト直列化形式を使用する場合 
// デフォルトのシリアライズ形式を持つ同期されたクラス用のwriteObject 
private synchronized void writeObject(ObjectOutputStream s) throws IOException { 
s.defaultWriteObject(); 
} 
 作成するすべてのシリアライズ可能なクラスに、明示的なシリアルバー 
ジョンUID を宣言すべき 
 非互換性の原因の可能性になるようなシリアルバージョンUID を排除 
(項目74) 
 実行時の生成するためのコストの高い計算を回避
シリアライズ形式のドキュメンテーション 
 @serial タグ 
 シリアライズ形式に含まれるフィールドにつける 
 private のフィールドであっても、public のAPI (シリアライズ形式)を定 
19 
義しているため、文書化しなければならない 
 ドキュメンテーションを特別のページ「直列化された形式」に掲載するよう、 
Javadoc ユティリティに指示する 
 @serialData タグ 
 クラスのシリアライズ形式を定義するメソッドにつける 
 private のメソッドフィールドであっても、public のAPI (シリアライズ形 
式)を定義しているため、文書化しなければならない 
 ドキュメンテーションを特別のページ「直列化された形式」に掲載するよう、 
Javadoc ユティリティに指示する
まとめ 
 クラスをシリアライズ可能にすべきと決めた場合(項目74) 
 シリアライズ形式について真剣に考えるべき 
 オブジェクトの論理的状態を適切に記述している形式 
 デフォルトのシリアライズ形式は、そうである場合にだけ使用する 
 そうでなければ、カスタムシリアライズ形式を設計する 
 クラスのシリアライズ形式の設計するのに多くの時間を割くべき 
 クラスの公開されたメソッドを設計するときと同様(項目40) 
 誤ったシリアライズ形式を選択すると 
20 
⇒ クラスの複雑さとパフォーマンスに永久的で否定的な影響

More Related Content

Viewers also liked

JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Appresso Engineering Team
 
マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded ExecutionAppresso Engineering Team
 
Java9 and Project Jigsaw
Java9 and Project JigsawJava9 and Project Jigsaw
Java9 and Project Jigsawtakezoe
 
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShellAmazon Web Services Japan
 

Viewers also liked (14)

Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73Effective Java 輪読会 項目71-73
Effective Java 輪読会 項目71-73
 
Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65Effective Java 輪読会 項目63-65
Effective Java 輪読会 項目63-65
 
JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文JavaScript 勉強会 ― 変数・演算子・文
JavaScript 勉強会 ― 変数・演算子・文
 
Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加Effective Java 輪読会 項目69-70追加
Effective Java 輪読会 項目69-70追加
 
Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56Effective Java 輪読会 項目53-56
Effective Java 輪読会 項目53-56
 
JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値JavaScript 勉強会 ― 型と値
JavaScript 勉強会 ― 型と値
 
Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62Effective Java 輪読会 項目60-62
Effective Java 輪読会 項目60-62
 
Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44Effective Java 輪読会 第7章 項目43-44
Effective Java 輪読会 第7章 項目43-44
 
Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48Effective Java 輪読会 項目45-48
Effective Java 輪読会 項目45-48
 
Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52Effective Java 輪読会 項目49-52
Effective Java 輪読会 項目49-52
 
マルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Executionマルチスレッド デザインパターン ― Single Threaded Execution
マルチスレッド デザインパターン ― Single Threaded Execution
 
20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)
 
Java9 and Project Jigsaw
Java9 and Project JigsawJava9 and Project Jigsaw
Java9 and Project Jigsaw
 
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
 

More from Appresso Engineering Team

Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Appresso Engineering Team
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Appresso Engineering Team
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Appresso Engineering Team
 
Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Appresso Engineering Team
 
Effective java 輪読会 第6章 項目30-31
Effective java 輪読会 第6章 項目30-31Effective java 輪読会 第6章 項目30-31
Effective java 輪読会 第6章 項目30-31Appresso Engineering Team
 
Effective java 輪読会 第5章 項目26-29
Effective java 輪読会 第5章 項目26-29Effective java 輪読会 第5章 項目26-29
Effective java 輪読会 第5章 項目26-29Appresso Engineering Team
 
Effective java 輪読会 第5章 項目23-25
Effective java 輪読会 第5章 項目23-25Effective java 輪読会 第5章 項目23-25
Effective java 輪読会 第5章 項目23-25Appresso Engineering Team
 
Effective java 輪読会 第4章 項目18-22
Effective java 輪読会 第4章 項目18-22Effective java 輪読会 第4章 項目18-22
Effective java 輪読会 第4章 項目18-22Appresso Engineering Team
 
Effective Java 輪読会 第4章 項目13-17
Effective Java 輪読会 第4章 項目13-17Effective Java 輪読会 第4章 項目13-17
Effective Java 輪読会 第4章 項目13-17Appresso Engineering Team
 
Effective java 輪読会 第3章 項目11, 12
Effective java 輪読会 第3章 項目11, 12Effective java 輪読会 第3章 項目11, 12
Effective java 輪読会 第3章 項目11, 12Appresso Engineering Team
 
Effective java 輪読会 第3章 項目8,9,10
Effective java 輪読会 第3章 項目8,9,10Effective java 輪読会 第3章 項目8,9,10
Effective java 輪読会 第3章 項目8,9,10Appresso Engineering Team
 
Effective java 輪読会 第2章 項目5,6,7
Effective java 輪読会 第2章 項目5,6,7Effective java 輪読会 第2章 項目5,6,7
Effective java 輪読会 第2章 項目5,6,7Appresso Engineering Team
 
Effective java 輪読会 第2章 項目1,2,3,4
Effective java 輪読会 第2章 項目1,2,3,4Effective java 輪読会 第2章 項目1,2,3,4
Effective java 輪読会 第2章 項目1,2,3,4Appresso Engineering Team
 

More from Appresso Engineering Team (15)

Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)Java Day Tokyo 2014 まとめ (chen)
Java Day Tokyo 2014 まとめ (chen)
 
Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59Effective java 輪読会 項目57-59
Effective java 輪読会 項目57-59
 
Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42Effective Java 輪読会 第7章 項目41-42
Effective Java 輪読会 第7章 項目41-42
 
Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40Effective Java 輪読会 第7章 項目38-40
Effective Java 輪読会 第7章 項目38-40
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37
 
Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34Effective java 輪読会 第6章 項目32-34
Effective java 輪読会 第6章 項目32-34
 
Effective java 輪読会 第6章 項目30-31
Effective java 輪読会 第6章 項目30-31Effective java 輪読会 第6章 項目30-31
Effective java 輪読会 第6章 項目30-31
 
Effective java 輪読会 第5章 項目26-29
Effective java 輪読会 第5章 項目26-29Effective java 輪読会 第5章 項目26-29
Effective java 輪読会 第5章 項目26-29
 
Effective java 輪読会 第5章 項目23-25
Effective java 輪読会 第5章 項目23-25Effective java 輪読会 第5章 項目23-25
Effective java 輪読会 第5章 項目23-25
 
Effective java 輪読会 第4章 項目18-22
Effective java 輪読会 第4章 項目18-22Effective java 輪読会 第4章 項目18-22
Effective java 輪読会 第4章 項目18-22
 
Effective Java 輪読会 第4章 項目13-17
Effective Java 輪読会 第4章 項目13-17Effective Java 輪読会 第4章 項目13-17
Effective Java 輪読会 第4章 項目13-17
 
Effective java 輪読会 第3章 項目11, 12
Effective java 輪読会 第3章 項目11, 12Effective java 輪読会 第3章 項目11, 12
Effective java 輪読会 第3章 項目11, 12
 
Effective java 輪読会 第3章 項目8,9,10
Effective java 輪読会 第3章 項目8,9,10Effective java 輪読会 第3章 項目8,9,10
Effective java 輪読会 第3章 項目8,9,10
 
Effective java 輪読会 第2章 項目5,6,7
Effective java 輪読会 第2章 項目5,6,7Effective java 輪読会 第2章 項目5,6,7
Effective java 輪読会 第2章 項目5,6,7
 
Effective java 輪読会 第2章 項目1,2,3,4
Effective java 輪読会 第2章 項目1,2,3,4Effective java 輪読会 第2章 項目1,2,3,4
Effective java 輪読会 第2章 項目1,2,3,4
 

Recently uploaded

論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 

Recently uploaded (10)

論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 

Effective Java 輪読会 項目74-75

  • 1. Effective Java 輪読会 Item 74-75 開発部陳映融2014/3/12
  • 2. 第11章シリアライズ  項目74 Serializable を注意して実装する  項目75 カスタムシリアライズ形式の使用を検討する  項目76 防御的にreadObject を書く  項目77 インスタンス制御に対しては、readResolve よりenum 型を選 ぶ  項目78 シリアライズされたインスタンスの代わりに、シリアライズ・プロキ シを検討する ※ スペースの関係で、以下では一部の「シリアライズ」を「直列化」として表記 2
  • 3. Item 74 Serializable を注意して実装する
  • 4. Serializable を実装すること  クラスのインスタンスをシリアライズ可能にすること 4  誤解:シリアライズ可能にするのは簡単で、大した努力はいらない  「クラス宣言にimplements Serializable を追加するだけでできる」 ⇒ 簡単にできるけど、長期的なスパンではひどい目にあうことに...  Serializable を実装する際の主要コスト  一旦リリースされるとクラスの実装を変更する柔軟性が低下  バグやセキュリティホールの可能性が増大  新しいバージョンのクラスをリリースすることに関連するテストの負荷が増大 ⇒ Serializable インタフェースの実装は軽く考えて決めることではない!
  • 5. クラスの実装変更柔軟性への影響  シリアライズ可能=シリアライズ形式を公開API に含める 5  デフォルトだとシリアライズ形式は最初の内部表現に結びつける  パッケージプライベートとprivate のインスタンスフィールドも公開API に ⇒ フィールドへのアクセスを最小限にする実践(項目13)が無駄になる ⇒ 長期間付き合える高品質のシリアライズ形式を注意深く設計すべき(項目75,78)  シリアライズ可能性に伴う発展に対する制約の例  シリアルバージョンUID(ストリーム一意識別子)  明示的指定しなければ、自動生成される値が適用される  自動生成される値は実装のインタフェースやメンバからの影響を受ける  クラスの実装を変更するとその値が変更される ⇒ 明示的な宣言がないと互換性を失い、実行時にInvalidClassException
  • 6. バグやセキュリティホールの可能性  シリアライズ=オブジェクト生成に関する言語外の仕組み 6  ディシリアライズ=隠れたコンストラクタ  ディシリアライズの(コンストラクタとしての)責任  本当のコンストラクタにより確立された不変式を保証しなければならない  生成中オブジェクト内部へのアクセスをガードしなければならない  デフォルトのディシリアライズの仕組みへの依存 ⇒ オブジェクトを不変式破壊と不正アクセスのリスクに晒すこと
  • 7. リリースに関連するテストの負荷  クラス互換性を維持するためのテストの組み合わせ 7  新しいリリースでシリアライズ⇒ 今までの古いリリースでディシリアライズ  今までの古いリリースでシリアライズ⇒ 新しいリリースでディシリアライズ ⇒ リリース数が増えると大変なことに...  互換性テストの内容  バイナリ互換性:バイナリ形式の互換性  セマンティック互換性:オブジェクトの意味の互換性 ⇒ 自動化での構築ができない  互換性テストの必要性  変更量に依存、変更量が大きいほど、テストの必要性が増大  注意深く設計されたカスタムシリアライズ形式ではテスト必要性は減る
  • 8. Serializable を実装すべきか  クラスを実装するごとに、コストと恩恵を評価する  シリアライズに依存したフレームワークでクラスが使用される場合 8  例えばオブジェクトの転送や永続化に関するフレームワーク ⇒ Serializable を実装することは必要  Serializable を実装必須の他のクラスのコンポーネントとして ⇒ Serializable を実装すると、クラスの使用を容易にする  一般則として  コレクションクラスや値クラスはSerializable を実装すべき  活動的な実体を表すクラスはSerializable をめったに実装すべきでない
  • 9. Serializable を実装すべきか  継承のために設計されたクラス(インタフェースも基本的に同じ) 9 ⇒ Serializable をめったに実装すべきでない  例外として、シリアライズに依存するフレームワークを使用する場合  内部クラス  クラス定義との対応が定義されず、デフォルトのシリアライズ形式は不明確  無名クラスやローカルクラスの名前  コンパイラ生成による人工的フィールド  エンクロージングインスタンス参照を保存用  外部スコープからローカル変数値を保存用 ⇒ Serializable を実装すべきではない  ただしstatic のメンバークラスはSerializable 実装できる
  • 10. 継承のために設計されたクラス  Serializable を実装するケース  シリアライズ可能かつ拡張可能で、 10 インスタンスフィールドを持つクラスを実装する際の注意事項  インスタンスフィールドがデフォルト値に初期化されると成り立たない不変式あるか?  クラスにそのような不変式がある場合は以下メソッドを追加 // 状態を持ち拡張可能・シリアライズ可能クラスに対するreadObjectNoData を追加 private void readObjectNoData() throws InvalidObjectException { throw new InvalidObjectException(“Stream data required”);  【要確認】サブクラスインスタンスのディシリアライズ処理において、ディシリアライズし ようとするオブジェクトが自クラスをスーパークラスとして列挙していない場合、フィール ドを適切な値に設定するためにreadObjectNoData は呼び出される  要するに、バージョンの違うサブクラスのオブジェクトをディシリアライズする状況  【Java オブジェクト直列化仕様】3.5 readObjectNoData メソッド  【stackoverflow】Java: When to add readObjectNoData() during serialization? }
  • 11. 継承のために設計されたクラス  Serializable を実装しないケース  パラメータなしコンストラクタの提供を検討する 11 ⇒ サブクラスのシリアライズ可能の拡張性を残すように  不変式がすべて確立されるオブジェクトを生成するのが最善  不変式の確立にクライアントの情報提供が必要な場合は要注意 public abstract class AbstractFoo { ... // オブジェクトの完全性を意識して、アトミック参照で初期化状態を管理 private final AtomicReference<State> init = new AtomicReference<>(State.NEW); protected AbstractFoo(int x, int y) { initialize(x, y); } // オブジェクトの生成手段のみ提供、別途初期化メソッドの呼び出しが必要 protected AbstractFoo() {} // 未初期化時の初期化メソッド protect final void initialize(int x, int y) { ... } // 内部状態の正しさを保証する private void checkInit() { ... } ... }
  • 12. まとめ  Serializable の実装の容易さは見かけ倒し  短期間の使い捨てのクラスでなければ、Serializable を実装するか は真剣に決めるべき  Serializable を実装するかを決める場合、特に継承のために設計さ れたクラスは注意を払うべき  サブクラスでSerializable を実装・禁止することの中間的な設計ポイント 12 は、アクセス可能なパラメタなしコンストラクタを提供 ⇒ サブクラスがSerializable を実装することを許すが、強制はしない
  • 14. デフォルト直列化形式の受け入れ  時間制約がある中でクラスを作成する場合、適切な方法として  最善のAPI 設計に努力を集中すべき  使い捨てのクラスで実装して、後のリリースで置き換える ⇒ シリアライズ可能なクラスのシリアライズ形式はあとのリリースにも影響 14 (特にデフォルトのシリアライズ形式)  デフォルトのシリアライズ形式を受け入れる?  受け入れる前に、適切かどうかを最初に検討しなくてはならない  判断基準:オブジェクトの論理表現として適切か  デフォルトのシリアライズ形式はオブジェクトの物理表現を符号化したもの  論理表現と物理表現が同じであれば、おそらく適切  適切であると判断したら  不変式やとセキュリティを保証するため、多くの場合はreadObject メソッドを提 供しなければならない
  • 15. 適切でないデフォルト直列化形式の使用  デフォルト直列化形式の使用が適切でない例  StringList (p.286) 15  論理データ:文字列の列  物理表現:リンクリスト  適切でないデフォルトのシリアライズ形式の使用のデメリット  公開APIが現在の内部表現に永久拘束される  内部の実装が変わっても古い実装に関するコードは取り除くことできない  過剰な空間を消費する可能性がある  データを使いやすくするための仕組みの構造をシリアライズする価値はない  過剰な時間を消費する可能性がある  実装によってコストの高い検索を行うことになる場合も  スタックオーバーフローを起こす可能性がある  クラスの構造によって再帰的な検索がスタックオーバーフローを起こすかも
  • 16. 適切な直列化形式を持つクラスの実装  実装例: StringList (p.286)  シリアライズ形式:リスト内の文字列数と、文字列自身 16  物理表現の詳細は取り除かれる  transient 修飾子でインスタントフィールドを標記  defaultWriteObject/defaultReadObject メソッドの呼び出し  すべてのインスタントフィールドがtransient ならば、技術的には呼び出し を省くことは許されるが、推奨しない  後方互換性と前方互換性を保ちながら、あとのリリースでtransient でない フィールドを追加可能
  • 17. transient 識別子の使用  インスタントフィールドがデフォルト直列化形式から省かれることを示す  フィールドをtransient でないと決める前に、そのフィールドの値が、 オブジェクトの論理状態の一部であることを確認するべき  デフォルト直列化形式を使用した場合、transient と宣言したフィールド はデフォルト値に初期化される  デフォルト値がそのフィールドに対して受け入れられない場合の対処 17  受け入れられる値を回復させるreadObject メソッドを提供(項目76)  そのフィールドが最初に使用される時に遅延初期化を行う(項目71)
  • 18. シリアライズ形式と関係ない注意事項  オブジェクト全体の状態を読み出す他のメソッドに課す同期をオブジェクト のシリアライズにも課さなければならない  例えば、すべてのメソッドを同期することでスレッド安全性を達成しているスレッ 18 ドセーフのオブジェクトで、デフォルト直列化形式を使用する場合 // デフォルトのシリアライズ形式を持つ同期されたクラス用のwriteObject private synchronized void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); }  作成するすべてのシリアライズ可能なクラスに、明示的なシリアルバー ジョンUID を宣言すべき  非互換性の原因の可能性になるようなシリアルバージョンUID を排除 (項目74)  実行時の生成するためのコストの高い計算を回避
  • 19. シリアライズ形式のドキュメンテーション  @serial タグ  シリアライズ形式に含まれるフィールドにつける  private のフィールドであっても、public のAPI (シリアライズ形式)を定 19 義しているため、文書化しなければならない  ドキュメンテーションを特別のページ「直列化された形式」に掲載するよう、 Javadoc ユティリティに指示する  @serialData タグ  クラスのシリアライズ形式を定義するメソッドにつける  private のメソッドフィールドであっても、public のAPI (シリアライズ形 式)を定義しているため、文書化しなければならない  ドキュメンテーションを特別のページ「直列化された形式」に掲載するよう、 Javadoc ユティリティに指示する
  • 20. まとめ  クラスをシリアライズ可能にすべきと決めた場合(項目74)  シリアライズ形式について真剣に考えるべき  オブジェクトの論理的状態を適切に記述している形式  デフォルトのシリアライズ形式は、そうである場合にだけ使用する  そうでなければ、カスタムシリアライズ形式を設計する  クラスのシリアライズ形式の設計するのに多くの時間を割くべき  クラスの公開されたメソッドを設計するときと同様(項目40)  誤ったシリアライズ形式を選択すると 20 ⇒ クラスの複雑さとパフォーマンスに永久的で否定的な影響