Java | 基礎文法:条件分岐のネスト

Java Java
スポンサーリンク

条件分岐のネストの全体像

条件分岐のネストは、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・マップ・ポリモーフィズムで構造化」の三本柱で浅く保つ。複合条件は意味のある名前の真偽値に分解し、短絡評価で軽い→重いの順に並べる。重複チェックをなくし、分岐の責務は小さなメソッドや型へ分配する——この型が身につけば、分岐は読みやすく、変更にも強くなります。

タイトルとURLをコピーしました