目次
要約
- 分岐:
if / else if / else
とswitch
(式)を使い分ける - 反復:
for / while / do-while / for-each
を用途で選択 - 制御:
break / continue / return
と ラベルで外側ループ制御も可 - 補助:三項演算子
?:
、instanceof
パターンマッチ、ガード節で可読性向上
1. 分岐:if / else if / else
int score = 72;
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("D");
}
ポイント
- 条件が短い順よりも意図が明確な順で(例:範囲の上から下へ)
- 複雑化しそうなら 早期return(ガード節) を検討
2. 分岐:switch(従来/式)
2.1 従来のswitch(break
必須)
String role = "USER";
switch (role) {
case "ADMIN":
authorizeAll();
break;
case "USER":
authorizeLimited();
break;
default:
deny();
}
break
を書き忘れるとフォールスルー
2.2 switch 式(Java 14+)
int n = 8;
String label = switch (n) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
case 6 -> "D";
default -> "F";
};
複数文が必要ならyield
:
String msg = switch (role) {
case "ADMIN" -> "all access";
case "USER" -> {
logAccess(role);
yield "limited";
}
default -> "denied";
};
ポイント:式は値を返すため、変数初期化に有効/break
不要で安全
3. 反復:for / while / do-while / for-each
3.1 伝統的for
for (int i = 0; i < 10; i++) {
process(i);
}
- 添字が必要なときに適する
3.2 while
while (hasNext()) {
handle(next());
}
- 条件を先に評価。0回もあり得る
3.3 do-while
do {
readOnce();
} while (needMore());
- 本体を最低1回は実行
3.4 拡張for(for-each)
List<String> names = List.of("A","B","C");
for (String s : names) {
System.out.println(s);
}
- 要素列挙が目的なら最有力。インデックス不要で可読
4. ループ制御:break / continue と ラベル
// break/continue
for (int i = 0; i < 10; i++) {
if (i == 5) continue; // 5をスキップ
if (i == 8) break; // 8でループ終了
}
// ラベル付き break(多重ループを一気に抜ける)
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 2) break outer; // outerループを抜ける
}
}
注意:ラベル多用は可読性低下。関数分割やフラグ変数回避を検討
5. 三項演算子(条件演算子)?:
int age = 20;
String category = (age >= 18) ? "adult" : "child";
- 短い条件分岐に限定して使う(ネスト禁止)
6. instanceof
パターンマッチ(Java 16+)
Object obj = "hello";
if (obj instanceof String s && s.length() > 3) {
System.out.println(s.toUpperCase()); // 直接sが使える
}
instanceof
後のキャスト不要で簡潔・安全
7. ガード節(早期return)でネスト削減
void register(User u) {
if (u == null) return; // 早期リターン
if (!u.isValid()) { log("invalid"); return; }
save(u);
}
- 「例外条件を先に排除」→ 本筋の処理が浅いネストで書ける
8. 実用サンプル(1ファイル)
import java.util.List;
public class ControlFlowSample {
static String grade(int score) {
// switch式で値を返す
return switch (score / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
case 6 -> "D";
default -> "F";
};
}
static int findFirstEven(List<Integer> xs) {
// for-each と 早期return
for (int n : xs) {
if (n % 2 == 0) return n;
}
return -1; // 見つからない場合
}
public static void main(String[] args) {
System.out.println(grade(83)); // B
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
System.out.println("break outer");
break outer;
}
}
}
Object obj = "hi";
if (obj instanceof String s && !s.isEmpty()) {
System.out.println(s.repeat(2)); // hihi
}
}
}
ベストプラクティス要点
- 分岐はswitch式で漏れを減らす(
default
で安全側) - 反復はfor-each優先、添字が必要な場合のみ従来for
- 複雑な条件は意味のあるメソッド名に抽出(例:
isEligible()
) - 早期returnでネストを浅く、ラベルの多用は避ける
- 三項演算子は1行・単純条件まで(ネスト禁止)
次回は 基礎構文③ クラスとメソッド をご用意します。