この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: 条件分岐 (if文)
SEOタイトル: Java 条件分岐完全ガイド — if/switch/三項/パターンマッチ

この記事の要点
  • if / else if / else が基本。switch は等価判定のみだが多分岐で読みやすい
  • Java 14+ で switch 式 (-> アロー、yield) が追加 → break 忘れバグが消える
  • Java 21+ で pattern matching switch が標準化 → 型分岐が劇的に簡潔に
  • 三項演算子 ? : は短い分岐に。複雑になったら if へ戻す
  • 早期 return (Early Return) でネスト深さを下げる。ガード節パターン

if / else if / else

int score = 75;

if (score >= 90) {
    System.out.println("A");
} else if (score >= 80) {
    System.out.println("B");
} else if (score >= 70) {
    System.out.println("C");
} else {
    System.out.println("F");
}

// 1 行なら波括弧省略可 (ただし非推奨 → バグの温床)
if (x > 0) System.out.println("正");  // ★ 後で行を追加するとバグる

// ✅ 必ず波括弧を付ける (Google Java Style 推奨)
if (x > 0) {
    System.out.println("正");
}

三項演算子

int n = 5;
String sign = n > 0 ? "正" : (n < 0 ? "負" : "ゼロ");

// 変数代入や return と相性が良い
String greeting = isMorning ? "おはよう" : "こんにちは";
return user == null ? "Guest" : user.getName();

// ❌ 複雑になったら if へ戻す
String result = a > 0 ? (b > 0 ? (c > 0 ? "all+" : "ab+") : "a+") : "neg";
// ★ 読めない

switch 文 (旧記法)

String day = "MONDAY";

switch (day) {
    case "MONDAY":
    case "TUESDAY":
    case "WEDNESDAY":
    case "THURSDAY":
    case "FRIDAY":
        System.out.println("平日");
        break;                       // ★ break 忘れに注意 (fall-through)
    case "SATURDAY":
    case "SUNDAY":
        System.out.println("週末");
        break;
    default:
        System.out.println("不明");
}

switch 式 (Java 14+) ★ 推奨

// アロー記法 + 値を返せる + break 不要
String type = switch (day) {
    case "SATURDAY", "SUNDAY" -> "週末";
    case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "平日";
    default -> "不明";
};

// ブロック + yield
int hours = switch (day) {
    case "FRIDAY" -> {
        System.out.println("花金");
        yield 6;
    }
    case "SATURDAY", "SUNDAY" -> 0;
    default -> 8;
};

// switch 式は ★ 全パターン網羅必須 (網羅していないとコンパイルエラー)

pattern matching switch (Java 21+) ★ 最新

Object o = "Hello";

String describe = switch (o) {
    case Integer i when i > 0  -> "正の整数: " + i;
    case Integer i             -> "0以下の整数: " + i;
    case String s              -> "文字列: " + s;
    case int[] arr             -> "int 配列 長さ " + arr.length;
    case null                  -> "null!";
    default                    -> "その他";
};

// sealed クラスとの組み合わせ (網羅性チェック付き)
sealed interface Shape permits Circle, Square, Rectangle {}
record Circle(double r) implements Shape {}
record Square(double a) implements Shape {}
record Rectangle(double w, double h) implements Shape {}

double area(Shape s) {
    return switch (s) {
        case Circle c    -> Math.PI * c.r() * c.r();
        case Square sq   -> sq.a() * sq.a();
        case Rectangle r -> r.w() * r.h();
        // default 不要 (sealed なので網羅)
    };
}

null チェックの典型パターン

String s = getValue();

// 基本
if (s == null) {
    return "default";
}

// 短絡で安全に呼び出し
if (s != null && s.length() > 0) { ... }

// Optional を使う (Java 8+)
Optional<String> opt = Optional.ofNullable(s);
opt.ifPresent(v -> System.out.println(v));
String result = opt.orElse("default");

// Yoda 記法 (定数を左に置いてミスを防ぐ)
if (null == s) { ... }   // s が null かどうか
// if (s = null) ←代入と間違えても s 側にしておけばコンパイルエラーで気付ける

早期 return (Early Return) でネストを浅く

// ❌ ネストが深い
public String process(User u) {
    if (u != null) {
        if (u.isActive()) {
            if (u.getEmail() != null) {
                return u.getEmail().toLowerCase();
            } else {
                return "no email";
            }
        } else {
            return "inactive";
        }
    } else {
        return "null";
    }
}

// ✅ ガード節で早期 return
public String process2(User u) {
    if (u == null)             return "null";
    if (!u.isActive())         return "inactive";
    if (u.getEmail() == null)  return "no email";
    return u.getEmail().toLowerCase();
}

複雑な条件のリファクタリング

// ❌ 条件が呪文
if (user != null && user.getAge() >= 20 && user.getCountry().equals("JP")
    && (user.getStatus() == Status.ACTIVE || user.getStatus() == Status.VIP)) {
    sendCampaign(user);
}

// ✅ メソッド化 + 名前で意図を表現
if (isTargetForJapanAdultCampaign(user)) {
    sendCampaign(user);
}

private boolean isTargetForJapanAdultCampaign(User u) {
    if (u == null) return false;
    if (u.getAge() < 20) return false;
    if (!"JP".equals(u.getCountry())) return false;  // ★ "JP".equals でも NPE 防止
    return u.getStatus() == Status.ACTIVE || u.getStatus() == Status.VIP;
}

== と equals() の使い分け

比較対象使う
基本型 (int / long / double)==x == 0
String.equals()s.equals("abc")
String と null チェックYoda .equals()"abc".equals(s)
参照同一性==obj == this
enum==status == Status.ACTIVE
Integer / Long.equals()boxing 値はキャッシュ範囲外で == NG

FAQ

Q: switch と if、どちらを使うべき?
A: 等価判定の多分岐は switch (式) が読みやすい。範囲判定 (x > 0 等) は if。

Q: if (x = 5) のバグを防ぐには?
A: Java では条件式は boolean のみなので if (x = 5) はコンパイルエラーで気付けます (boolean 同士なら可)。

Q: else if の連続は何個まで OK?
A: 目安は 3〜4 個。それ以上は switch / Strategy パターン / Map による分岐表に置き換える。