条件分岐のネストの全体像
条件分岐のネストは、if/else を入れ子にして複数の前提やケースを順に判定する書き方です。複雑なロジックを表現できますが、深くなるほど読みづらく、バグが入りやすくなります。基本方針は「早期に弾いて浅く保つ」「役割ごとに分ける」「表を使って分岐をデータ化する」。この3つでネストを減らし、可読性と保守性を高めます。
典型パターンと安全な書き方
基本の入れ子と読みやすさの工夫
深いネストは「否定条件を先に弾く」「共通処理を早期 return で抜ける」ことで浅くできます。
// 悪い例:入れ子が深い
if (user != null) {
if (user.isActive()) {
if (!user.isBanned()) {
process(user);
}
}
}
// 良い例:ガード節で浅く
if (user == null) return;
if (!user.isActive()) return;
if (user.isBanned()) return;
process(user);
Java「何を満たせば進むか」を上から一直線で読めるように並べるのがコツです。
else の使い方を整理する
「早期 return」を使うと、else を減らせます。分岐の深さよりも直線の読みやすさを優先します。
int price(int qty) {
if (qty <= 0) return 0; // ガード
if (qty < 10) return 100 * qty; // 早期分岐
return 90 * qty; // 残り(デフォルト)
}
Java重要ポイントの深掘り:ネストを減らす手段
ガード節(前提違反を先に弾く)
「これ以降は前提が満たされている」と保証すると、内側の条件は単純になります。
void register(User u) {
if (u == null) throw new IllegalArgumentException("user must not be null");
if (!u.isEligible()) throw new IllegalStateException("not eligible");
save(u); // 以後は「有効なユーザー」として扱える
}
Java例外や早期 return を使い、否定条件をまとめて入口で処理します。
ケース分けを switch に寄せる(列挙型と相性がよい)
enum で区分を型にすると、switch で平らに書けます。
enum Plan { BASIC, PRO, ENTERPRISE }
int fee(Plan plan) {
return switch (plan) {
case BASIC -> 1000;
case PRO -> 3000;
case ENTERPRISE -> 10000;
};
}
Java「if の連続」より視線が跳ねず、漏れも防げます。
表で分岐をデータ化(マップ・関数テーブル)
条件と結果をデータにすると、コードのネストが消えます。
import java.util.Map;
import java.util.function.Function;
Map<String, Function<Order, Integer>> pricing = Map.of(
"JP", o -> o.qty() * 100,
"US", o -> o.qty() * 1_00,
"EU", o -> o.qty() * 90
);
int price(String region, Order o) {
var f = pricing.get(region);
if (f == null) throw new IllegalArgumentException("unsupported region: " + region);
return f.apply(o);
}
Java追加・変更はデータの更新だけで済み、分岐の複雑化を防げます。
分岐ごとの責務をメソッドへ分割
1つの関数で全部やろうとするとネストが深くなります。分岐単位の小さなメソッドへ切り出すと読みやすくなります。
void handle(Request r) {
if (isAuthFailed(r)) { respondUnauthorized(); return; }
if (isRateLimited(r)) { respondTooManyRequests(); return; }
processOk(r);
}
Java役割名のメソッドにすると「何をしているか」が名前で伝わります。
複合条件の整理術
条件の意味を名前に置き換える
複雑な論理式は「意味のある真偽値」に分解すると読みやすくなります。
boolean hasText = s != null && !s.isBlank();
boolean isAdult = age >= 18;
boolean canSubmit = hasText && isAdult;
if (canSubmit) submit();
Java名前の付け方が「質問文」になっていると、if の行がそのまま仕様書の文になります。
優先度と短絡評価を活用
軽いチェックを先に。重い処理は後に回すと効率的です。
if (token != null && isValid(token) && hasPermission(token)) {
// 左から軽い→重いで配列
}
Java短絡評価により、先の条件が false なら後続は評価されません。
よくある落とし穴と回避策
否定のネストで読みづらくなる
二重否定は脳内負荷が高いです。「否定条件を先に return」するか、肯定形に書き換えます。
// 悪い
if (!(user != null && user.isActive())) { /* ... */ }
// 良い
if (user == null) return;
if (!user.isActive()) return;
Java同じ条件の重複チェック
入口のガードで保証した前提を、内側で再度チェックしないようにします。ロジックの層ごとに「どこで保証するか」を決めると、重複が消えます。
else の中でさらに if を重ねる
入れ子が深くなるサインです。早期 return や switch、メソッド分割へ置き換えます。
設計の引き出し:ネストを構造で消す
ポリモーフィズム(戦略パターン)で分岐を型へ
分岐の代わりに「正しい実装」を選ぶ設計へ。
interface Pricing { int fee(Order o); }
class Basic implements Pricing { public int fee(Order o) { return 1000; } }
class Pro implements Pricing { public int fee(Order o) { return 3000; } }
int fee(Pricing p, Order o) { return p.fee(o); } // 分岐が消える
Java「条件に応じたオブジェクト」を作る側に責務を寄せると、利用側のネストがゼロになります。
バリデーションは前処理でまとめる
検証結果をオブジェクト化し、後段は「有効な入力」として扱うとネストが浅くなります。
record Validation(boolean ok, String message) {}
Validation v = validate(req);
if (!v.ok()) { showError(v.message()); return; }
process(req);
Java例題で身につける
例 1: 複雑な if のフラット化
// Before
if (user != null) {
if (user.isActive()) {
if (!user.isBanned()) {
sendMail(user);
}
}
}
// After
if (user == null) return;
if (!user.isActive()) return;
if (user.isBanned()) return;
sendMail(user);
Java例 2: switch と enum でネストを解消
enum Status { NEW, PROCESSING, DONE, FAILED }
String label(Status s) {
return switch (s) {
case NEW -> "新規";
case PROCESSING -> "処理中";
case DONE -> "完了";
case FAILED -> "失敗";
};
}
Java例 3: 表で分岐をデータ化
import java.util.Map;
Map<String, Integer> rateByRegion = Map.of("JP", 10, "US", 8, "EU", 9);
int tax(int subtotal, String region) {
Integer rate = rateByRegion.get(region);
if (rate == null) throw new IllegalArgumentException("unknown region: " + region);
return subtotal * rate / 100;
}
Java仕上げのアドバイス(重要部分のまとめ)
条件分岐のネストは「否定条件を入口で弾く」「早期 return で直線化」「switch/enum・マップ・ポリモーフィズムで構造化」の三本柱で浅く保つ。複合条件は意味のある名前の真偽値に分解し、短絡評価で軽い→重いの順に並べる。重複チェックをなくし、分岐の責務は小さなメソッドや型へ分配する——この型が身につけば、分岐は読みやすく、変更にも強くなります。
