Javaコードアンチパターン 初級からプロまで知っておきたいミスと回避策
3,960円
(3,600円+税)
【注意】本書のEPUB版は固定レイアウト型になっております。文字の大きさの変更や検索、引用などはお使いいただけません。画面の大きい端末でご利用ください。
関連サイト
本書の関連ページが用意されています。
内容紹介
100の失敗から学ぶ、堅牢で効率的なJavaコーディングの鉄則。
Java静的解析エキスパートが見てきた失敗をもとに現場で役立つ実践知を解説!
本書は、Javaの神様と呼ばれる名著者Joshua Blochや開発者たちが評価し、本棚に置くべき一冊と推す、Java開発本の決定版です。
開発現場でJavaコードと向き合う中、些細なミスが引き起こす深刻なバグが発生すれば、時間と労力を浪費することになるでしょう。
そこで本書は、初級者からプロフェッショナルまでのすべての開発者が「犯しがちな、繰り返し起こり得るミス」に焦点を当てています。それらのミスを事前に回避して時間と労力を無駄にしない具体的なアドバイスを提供する実践的な指南集となっています。
静的解析ツールを活用して、常に優れたJavaコードを提供できるようにする方法、防御的コーディングによってコードをクリーンに保つ方法に加えて、独自のバグ対策プラグインの作成方法なども示します。
著者は、IntelliJ IDEAの開発元JetBrains社のテクニカルリードであり、Javaバイトコードの静的解析ツールの開発にも貢献するなど、静的解析の分野で10年の経験を持つ専門家です。
本書は、実際の現場で遭遇したコードから厳選した100項目の落とし穴をカバーしています。他者の失敗から学ぶことで、「真の現場力」を養うことができます。
※本書は『100 Java Mistakes and How to Avoid Them』(Manning Publications)の翻訳書です。
書誌情報
- 著者: Tagir Valeev(著), 柴田 芳樹(訳)
- 発行日: 2026-02-12 (紙書籍版発行日: 2026-02-12)
- 最終更新日: 2026-02-12
- バージョン: 1.0.0
- ページ数: 376ページ(PDF版換算)
- 対応フォーマット: PDF, EPUB
- 出版社: インプレス
対象読者
著者について
Tagir Valeev
統合開発環境などのツールを開発・提供するJetBrains GmbH(ドイツ法人。本社はチェコ)のテクニカルリード。Javaのチームに所属し、統合開発環境のIntelliJ IDEAでのJava言語をサポートしている。IntelliJ IDEA用の静的解析ツールとして多数のコードインスペクション機能を設計・開発。Javaテクノロジー/コミュニティのリーダーの称号であるJava Championに2020年に選考されたほか、コンピューターサイエンスの博士号を2006年に取得している。
柴田 芳樹

1959年11月生まれ。九州工業大学情報工学科で情報工学を学び、1984年同大学大学院で情報工学修士課程を修了。パロアルト研究所を含む米国ゼロックス社での5年間のソフトウェア開発も含め、UNIX(Solaris/Linux)、C、Mesa、C++、Java、Goなどを用いたさまざまなソフトウェア開発に従事してきた。2017年9月以降、Goによるウェブサービスのバックエンドソフトウェア開発に携わっている。JavaやGoの技術教育も行ってきており、私的な時間に技術書の翻訳や講演なども多く行っている。訳書は「Effective Java 第3版」「プログラミング言語Go」「プログラミング言語Java 第4版」(以上、丸善出版)、「Go言語 100Tips ありがちなミスを把握し、実装を最適化する」「スーパーユーザーなら知っておくべきLinuxシステムの仕組み」(以上、インプレス)、「ベタープログラマ」「アプレンティスシップ・パターン」(以上、オライリー・ジャパン)など20タイトル以上。
目次
序文
- まえがき
- 謝辞
- 著者紹介
- 本書について
第1章 コード品質の管理
- 1.1 コードレビューとペアプログラミング
- 1.2 コードスタイル
- 1.3 静的解析
- 1.3.1 Java向けの静的解析ツール
- 1.3.2 静的解析ツールの活用
- 1.3.3 静的解析の限界
- 1.3.4 不要な警告の抑制
- 1.4 自動テスト
- 1.5 ミューテーションカバレッジ
- 1.6 動的解析
- 1.7 コードアサーション
第2章 式
- 2.1 No.1:数値演算子の優先順位に関する誤った思い込み
- 2.1.1 ビットシフト
- 2.1.2 ビット演算子
- 2.2 No.2:条件式での括弧の欠落
- 2.2.1 &&と||の優先順位
- 2.2.2 条件演算子と加算
- 2.2.3 条件演算子とnull検査
- 2.3 No.3:加算のつもりが文字列結合
- 2.4 No.4:複数行の文字列リテラル
- 2.5 No.5:単項+
- 2.6 No.6:条件式における暗黙的な型変換
- 2.6.1 条件式におけるラッパークラスの数値
- 2.6.2 入れ子の条件式
- 2.7 No.7:非短絡評価の論理演算子を使う
- 2.8 No.8:&&と||の混同
- 2.9 No.9:可変長引数呼び出しの誤った使い方
- 2.9.1 あいまいな可変長引数呼び出し
- 2.9.2 配列とコレクションの混在
- 2.9.3 可変長引数呼び出しで基本データ型の配列を使う
- 2.10 No.10:条件演算子と可変長引数呼び出し
- 2.11 No.11:重要な戻り値を無視する
- 2.12 No.12:新たに作成したオブジェクトを使わない
- 2.13 No.13:間違ったメソッドにメソッド参照を結び付ける
- 2.14 No.14:メソッド参照で誤ったメソッドを使う
第3章 プログラム構造
- 3.1 No.15:不適切なif-else連鎖
- 3.2 No.16:前の条件に包含されている条件
- 3.3 No.17:switch文における意図しないフォールスルー
- 3.4 No.18:従来構文による不正な形式のfor ループ
- 3.5 No.19:ループ変数を使っていない
- 3.6 No.20:ループの方向が誤っている
- 3.7 No.21:ループのオーバーフロー
- 3.8 No.22:冪等なループ本体
- 3.9 No.23:正しくない初期化順序
- 3.9.1 static フィールド
- 3.9.2 サブクラスのフィールド
- 3.9.3 クラスの初期化順序
- 3.9.4 enumにおける初期化の循環
- 3.10 No.24:スーパークラスのメソッド呼び出しの漏れ
- 3.11 No.25:意図せずstaticと宣言されたフィールド
第4章 数値
- 4.1 No.26:8進リテラルの意図しない利用
- 4.2 No.27:数値のオーバーフロー
- 4.2.1 Javaでのオーバーフロー
- 4.2.2 int型の乗算結果をlong 型の変数に代入する
- 4.2.3 ファイルサイズ、時間、金額の計算
- 4.3 No.28:整数による除算における丸め
- 4.4 No.29:Integer.MIN_VALUEの絶対値
- 4.5 No.30:奇数判定と負の数値
- 4.6 No.31:精度が失われるワイドニング変換
- 4.7 No.32:無条件のナローイング変換
- 4.8 No.33:負の16進値
- 4.9 No.34:複合代入における暗黙的な型変換
- 4.10 No.35:除算と複合代入
- 4.11 No.36:short型の使用
- 4.12 No.37:ビット操作アルゴリズムを手作業で記述する
- 4.13 No.38:負のbyte値を忘れる
- 4.14 No.39:クランプ処理順序の誤り
- 4.15 No.40:特殊な浮動小数点数の誤用
- 4.15.1 符号付きゼロ:+0.0と-0.0
- 4.15.2 非数:NaN値
- 4.15.3 Double.MIN_VALUEは最小値ではない
第5章 代表的な例外
- 5.1 No.41:NullPointerException
- 5.1.1 nullの回避と防御的な検査
- 5.1.2 nullの代わりにOptional を使う
- 5.1.3 null許容性アノテーション
- 5.2 No.42:IndexOutOfBoundsException
- 5.3 No.43:ClassCastException
- 5.3.1 明示的なキャスト
- 5.3.2 ジェネリック型と暗黙のキャスト
- 5.3.3 異なるクラスローダー
- 5.4 No.44:StackOverflowError
- 5.4.1 再帰は深いが有限
- 5.4.2 無限再帰
第6章 文字列
- 6.1 No.45:charの値が文字であると仮定すること
- 6.2 No.46:予期しない大文字小文字の変換
- 6.3 No.47:デフォルトロケールでString.formatを使う
- 6.4 No.48:フォーマット引数の不一致
- 6.5 No.49:正規表現ではなく通常の文字列を使う
- 6.6 No.50:replaceAllを誤って使う
- 6.7 No.51:エスケープシーケンスを誤って使う
- 6.8 No.52:大文字と小文字が異なる文字列の比較
- 6.9 No.53:indexOfメソッドの結果を確認しない
- 6.10 No.54:indexOfの引数の取り違え
第7章 オブジェクトの比較
- 7.1 No.55:equalsメソッドの代わりに参照の等価性を使う
- 7.2 No.56:equals()が内容を比較すると仮定する
- 7.3 No.57:URL.equals()を使う
- 7.4 No.58:スケールが異なるBigDecimal同士の比較
- 7.5 No.59:無関係な型に対してequals()を使う
- 7.6 No.60:誤ったequals()実装
- 7.7 No.61:配列フィールドを含む誤ったhashCode()
- 7.8 No.62:equals()とhashCode()の不一致
- 7.9 No.63:compare()の特定の戻り値に依存する
- 7.10 No.64:等しいオブジェクトを比較したときに0を返さない
- 7.11 No.65:数値を比較するときに減算を使う
- 7.12 No.66:比較メソッドでNaN値を無視する
- 7.13 No.67:比較メソッドでオブジェクトをキーの並びとして表現しない
- 7.14 No.68:コンパレータからランダムな数値を返す
第8章 コレクションとマップ
- 8.1 No.69:関連のない型のオブジェクトを検索
- 8.2 No.70:単一のオブジェクトとコレクションを混同する
- 8.3 No.71:null非許容コレクションでのnullの検索
- 8.4 No.72:マップでnull値を使う
- 8.5 No.73:変更不可能なコレクションを変更しようとする
- 8.6 No.74:キーとして変更可能なオブジェクトを使う
- 8.7 No.75:HashMapやHashSetの出現順序に依存する
- 8.8 No.76:反復処理中の同時変更
- 8.9 No.77:List.remove()のオーバーロードを混同する
- 8.10 No.78:List.remove()の後で次の要素を飛ばしてしまう
- 8.11 No.79:Collection.removeIf()の中でコレクションを読み取る
- 8.12 No.80:Map.computeIfAbsent()における同時変更
- 8.13 No.81:Iteratorの契約に違反する
第9章 その他のライブラリメソッド
- 9.1 No.82:charをStringBuilderコンストラクタに渡す
- 9.2 No.83:ストリームAPIの処理連鎖内で副作用を発生させること
- 9.3 No.84:ストリームを2回消費する
- 9.4 No.85:許可されていない場所でストリームにnull値を使う
- 9.5 No.86:ストリームAPIの操作の契約に違反する
- 9.6 No.87:instanceofの代わりにgetClass()を使う
- 9.7 No.88:enum、アノテーション、クラスに対してgetClass()を使う
- 9.8 No.89:文字列からブーリアンへの誤った変換
- 9.9 No.90:日付フォーマットにおける誤った書式指定子
- 9.10 No.91:弱い参照やソフトな参照の意図しない失効
- 9.11 No.92:世界が安定していると仮定する
- 9.12 No.93:並行に更新されるデータ構造へのアトミックではないアクセス
第10章 単体テスト
- 10.1 No.94:assert文における副作用
- 10.2 No.95:不正な形式のアサーションメソッド呼び出し
- 10.3 No.96:不正な形式の例外テスト
- 10.4 No.97:テストメソッドからの早すぎる終了
- 10.5 No.98:単体テストでAssertionErrorを無視する
- 10.6 No.99:等値性の契約の検査にassertNotEquals()を使う
- 10.7 No.100:不正な形式のテストメソッド
付録A 静的解析用アノテーション
- A.1 アノテーションパッケージ
- A.2 アノテーションの種類
付録B 静的解析ツールの拡張
- B.1 Error Proneプラグイン
- B.2 SpotBugsプラグイン
- B.3 IntelliJ IDEAプラグイン
- B.4 IntelliJ IDEAでの構造検索と置換の利用
