超小ネタですが、Effective Java の 第2版 と 第3版 を見出しレベルで比較してみました。細かい言い回しの変更は含んでいません。というか、はじめに と付録の 第2版に対応する項目 を見ればだいたい新しい項目は把握できると思われます。が、そこをあえて項目同士を横に並べる形で一覧化してみました。ご参考まで。
第3版を購入したけど積読中の方、とりあえず新しく追加された項目を読んでみるのはいかがでしょう。
章レベルでは第3版から『第7章 ラムダとストリーム』が追加されています。項目レベルでは下記の通りです。左列に NEW と記載があるものが新しく追加されたか、他項目に移行されたものです。
また、第2版の『項目21 戦略を表現するために関数オブジェクトを使用する』『項目73 スレッドグループを避ける』は第3版では削除されています。(項目21については第3版では Lambda に移行された模様)
※ 太字下線 の行は章見出しです。
| - | # | 第2版 | # | 第3版 |
|---|---|---|---|---|
| 1 | はじめに | 1 | はじめに | |
| 2 | オブジェクトの生成と消滅 | 2 | オブジェクトの生成と消滅 | |
| 1 | コンストラクタの代わりにstaticファクトリーメソッドを検討する | 1 | コンストラクタの代わりにstaticファクトリーメソッドを検討する | |
| 2 | 数多くのコンストラクタパラメータに直面した時にはビルダーを検討する | 2 | 多くのコンストラクタパラメータに直面した時にはビルダーを検討する | |
| 3 | privateのコンストラクタかenum型でシングルトン特性を強制する | 3 | privateのコンストラクタかenum型でシングルトン特性を強制する | |
| 4 | privateのコンストラクタでインスタンス化不可能を強制する | 4 | privateのコンストラクタでインスタンス化不可能を強制する | |
| NEW | 5 | 資源を直接結び付けるよりも依存性注入を選ぶ | ||
| 5 | 不必要なオブジェクトの生成を避ける | 6 | 不必要なオブジェクトの生成を避ける | |
| 6 | 廃れたオブジェクト参照を取り除く | 7 | 使われなくなったオブジェクト参照を取り除く | |
| 7 | ファイナライザを避ける | 8 | ファイナライザとクリーナを避ける | |
| NEW | 9 | try-finallyよりもtry-with-resourcesを選ぶ | ||
| 3 | すべてのオブジェクトに共通のメソッド | 3 | すべてのオブジェクトに共通のメソッド | |
| 8 | equalsをオーバーライドする時は一般契約に従う | 10 | equalsをオーバーライドする時は一般契約に従う | |
| 9 | equalsをオーバーライドする時は、常にhashCodeをオーバーライドする | 11 | equalsをオーバーライドする時は、常にhashCodeをオーバーライドする | |
| 10 | toStringを常にオーバーライドする | 12 | toStringを常にオーバーライドする | |
| 11 | cloneを注意してオーバーライドする | 13 | cloneを注意してオーバーライドする | |
| 12 | Comparableの実装を検討する | 14 | Comparableの実装を検討する | |
| 4 | クラスとインタフェース | 4 | クラスとインタフェース | |
| 13 | クラスとメンバーへのアクセス可能性を最小限にする | 15 | クラスとメンバーへのアクセス可能性を最小限にする | |
| 14 | publicのクラスでは、publicのフィールドではなく、アクセッサーメソッドを使う | 16 | publicのクラスでは、publicのフィールドではなく、アクセッサーメソッドを使う | |
| 15 | 可変性を最小限にする | 17 | 可変性を最小限にする | |
| 16 | 継承よりコンポジションを選ぶ | 18 | 継承よりコンポジションを選ぶ | |
| 17 | 継承のために設計および文書化する、でなければ継承を禁止する | 19 | 継承のために設計および文書化する、でなければ継承を禁止する | |
| 18 | 抽象クラスよりインタフェースを選ぶ | 20 | 抽象クラスよりインタフェースを選ぶ | |
| NEW | 21 | 将来のためにインタフェースを選ぶ | ||
| 19 | 型を定義するためだけにインタフェースを使用する | 22 | 型を定義するためだけにインタフェースを使う | |
| 20 | タグ付クラスよりクラス階層を選ぶ | 23 | タグ付きクラスよりもクラス階層を選ぶ | |
| DROP | 21 | 戦略を表現するために関数オブジェクトを使用する | ||
| 22 | 非staticのメンバークラスよりstaticのメンバークラスを選ぶ | 24 | 非staticのメンバークラスよりもstaticのメンバークラスを選ぶ | |
| NEW | 25 | ソースファイルを単一のトップレベルのクラスに限定する | ||
| 5 | ジェネリックス | 5 | ジェネリックス | |
| 23 | 新たなコードで原型を使用しない | 26 | 原型を使わない | |
| 24 | 無検査警告を取り除く | 27 | 無検査警告を取り除く | |
| 25 | 配列よりリストを選ぶ | 28 | 配列よりもリストを選ぶ | |
| 26 | ジェネリック型を使用する | 29 | ジェネリック型を使う | |
| 27 | ジェネリックメソッドを使用する | 30 | ジェネリックメソッドを使う | |
| 28 | APIの柔軟性向上のために境界ワイルドカードを使用する | 31 | APIの柔軟性向上のために境界ワイルドカードを使う | |
| NEW | 32 | ジェネリックスと可変長引数を注意して組み合わせる | ||
| 29 | 型安全な異種コンテナーを検討する | 33 | 型安全な異種コンテナを検討する | |
| 6 | enumとアノテーション | 6 | enumとアノテーション | |
| 30 | int定数の代わりにenumを使用する | 34 | int定数の代わりにenumを使う | |
| 31 | 序数の代わりにインスタンスフィールドを使用する | 35 | 序数の代わりにインスタンスフィールドを使う | |
| 32 | ビットフィールドの代わりにEnumSetを使用する | 36 | ビットフィールドの代わりにEnumSetを使う | |
| 33 | 序数インデックスの代わりにEnumMapを使用する | 37 | 序数インデックスの代わりにEnumMapを使う | |
| 34 | 拡張可能なenumをインタフェースで模倣する | 38 | 拡張可能なenumをインタフェースで模倣する | |
| 35 | 命名パターンよりアノテーションを選ぶ | 39 | 命名パターンよりもアノテーションを選ぶ | |
| 36 | 常にOverrideアノテーションを使用する | 40 | 常にOverrideアノテーションを使う | |
| 37 | 型を定義するためにマーカーインタフェースを使用する | 41 | 型を定義するためにマーカーインタフェースを使う | |
| NEW | 7 | ラムダとストリーム | ||
| NEW | 42 | 無名クラスよりもラムダを選ぶ | ||
| NEW | 43 | ラムダよりもメソッド参照を選ぶ | ||
| NEW | 44 | 標準の関数型インタフェースを使う | ||
| NEW | 45 | ストリームを注意して使う | ||
| NEW | 46 | ストリームで副作用のない関数を選ぶ | ||
| NEW | 47 | 戻り値型としてStreamよりもCollectionを選ぶ | ||
| NEW | 48 | ストリームを並列化するときは注意を払う | ||
| 7 | メソッド | 8 | メソッド | |
| 38 | パラメータの正当性を検査する | 49 | パラメータの正当性を検査する | |
| 39 | 必要な場合には、防御的にコピーする | 50 | 必要な場合、防御的にコピーする | |
| 40 | メソッドのシグニチャを注意深く設計する | 51 | メソッドのシグニチャを注意深く設計する | |
| 41 | オーバーロードを注意して使用する | 52 | オーバーロードを注意して使う | |
| 42 | 可変長引数を注意して使用する | 53 | 可変長引数を注意して使う | |
| 43 | nullではなく、空配列か空コレクションを返す | 54 | nullではなく、空コレクションか空配列を返す | |
| NEW | 55 | オプショナルを注意して返す | ||
| 44 | すべての公開API要素に対してドキュメントコメントを書く | 56 | すべての公開API要素に対してドキュメントコメントを書く | |
| 8 | プログラミング一般 | 9 | プログラミング一般 | |
| 45 | ローカル変数のスコープを最小限にする | 57 | ローカル変数のスコープを最小限にする | |
| 46 | 従来のforループよりfor-eachループを選ぶ | 58 | 従来のforループよりfor-eachループを選ぶ | |
| 47 | ライブラリーを知り、ライブラリーを使う | 59 | ライブラリを知り、ライブラリを使う | |
| 48 | 正確な答えが必要ならば、floatとdoubleを避ける | 60 | 正確な答えが必要ならば、floatとdoubleを避ける | |
| 49 | ボクシングされた基本データより基本データ型を選ぶ | 61 | ボクシングされた基本データよりも基本データ型を選ぶ | |
| 50 | 他の型が適切な場所では、文字列を避ける | 62 | 他の型が適切な場所では、文字列を避ける | |
| 51 | 文字列結合のパフォーマンスに用心する | 63 | 文字列結合のパフォーマンスに用心する | |
| 52 | インタフェースでオブジェクトを参照する | 64 | インタフェースでオブジェクトを参照する | |
| 53 | リフレクションよりインタフェースを選ぶ | 65 | リフレクションよりもインタフェースを選ぶ | |
| 54 | ネイティブメソッドを注意して使用する | 66 | ネイティブメソッドを注意して使う | |
| 55 | 注意して最適化する | 67 | 注意して最適化する | |
| 56 | 一般的に受け入れられている命名規約を守る | 68 | 一般的に受け入れられている命名規約を守る | |
| 9 | 例外 | 10 | 例外 | |
| 57 | 例外的状態にだけ例外を使用する | 69 | 例外的状態にだけ例外を使う | |
| 58 | 回復可能な状態にはチェックされる例外を、プログラミングエラーには実行時例外を使用する | 70 | 回復可能な状態にはチェックされる例外を、プログラミングエラーには実行時例外を使う | |
| 59 | チェックされる例外を不必要に使用するのを避ける | 71 | チェックされる例外を不必要に使うのを避ける | |
| 60 | 標準例外を使用する | 72 | 標準的な例外を使う | |
| 61 | 抽象概念に適した例外をスローする | 73 | 抽象概念に適した例外をスローする | |
| 62 | 各メソッドがスローするすべての例外を文書化する | 74 | 各メソッドがスローするすべての例外を文書化する | |
| 63 | 詳細メッセージにエラー記録情報を含める | 75 | 詳細メッセージにエラー記録情報を含める | |
| 64 | エラーアトミック性に努める | 76 | エラーアトミック性に努める | |
| 65 | 例外を無視しない | 77 | 例外を無視しない | |
| 10 | 並行性 | 11 | 並行性 | |
| 66 | 共有された可変データへのアクセスを同期する | 78 | 共有された可変データへのアクセスを同期する | |
| 67 | 過剰な同期は避ける | 79 | 過剰な同期は避ける | |
| 68 | スレッドよりエグゼキューターとタスクを選ぶ | 80 | スレッドよりもエグゼキュータ、タスク、ストリームを選ぶ | |
| 69 | waitとnotifyよりコンカレンシーユーティリティを選ぶ | 81 | waitとnotifyよりも並行処理ユーティリティを選ぶ | |
| 70 | スレッド安全性を文書化する | 82 | スレッド安全性を文書化する | |
| 71 | 遅延初期化を注意して使用する | 83 | 遅延初期化を注意して使う | |
| 72 | スレッドスケジューラに依存しない | 84 | スレッドスケジューラに依存しない | |
| DROP | 73 | スレッドグループを避ける | ||
| 11 | シリアライズ | 12 | シリアライズ | |
| NEW | 85 | Javaのシリアライズよりも代替手段を選ぶ | ||
| 74 | Serializableを注意して実装する | 86 | Serializableを細心の注意を払って実装する | |
| 75 | カスタムシリアライズ形式の使用を検討する | 87 | カスタムシリアライズ形式の使用を検討する | |
| 76 | 防御的にreadObjectを書く | 88 | 防御的にreadObjectメソッドを書く | |
| 77 | インスタンス制御に対しては、readResolveよりenum型を選ぶ | 89 | インスタンス制御に対しては、readResolveよりもenum型を選ぶ | |
| 78 | シリアライズされたインスタンスの代わりに、シリアライズ・プロキシを検討する | 90 | シリアライズされたインスタンスの代わりに、シリアライズ・プロキシを検討する |
その他
長年、本書の第2版は Java の必読書としてしばしば挙げられていますが、内容が古くなっていたり、新しい機能に追従できていないところはありました。以前よりも Java のアップデートサイクルは早くなっているため、特に入門者に書籍をおすすめするときには、古い内容が含まれていないか、移行された機能がないか、十分に注意したいところです。
ところで、全体的に Optional がカタカナで書かれているのはなぜだろう...。