1. 条件分岐:条件に基づいてコードの実行パスを選択する
条件分岐は、異なる条件に基づいて異なるコードブロックを実行するために使用されます。Javaでは主に `if` 系列と `switch` 文が利用されます。
単純な if: 1つの条件を評価する
特徴: 1つの条件を評価し、条件が真であればコードブロックを実行します。
構文テンプレート:
if (ブール式) {
// 条件が true の場合に実行されるコード
}
コード例:
int score = 85;
// スコアが合格点以上かどうかを確認
if (score >= 60) {
System.out.println("試験に合格しました"); // 出力: 試験に合格しました
}
一般的な落とし穴: 大括弧 `{}` を省略すると、後続のステートメントが `if` の制御範囲内に含まれる可能性があり、論理エラーを引き起こすことがあります。
// エラー例: 大括弧を省略
if (score >= 60)
System.out.println("合格");
System.out.println("もっと頑張ろう"); // 条件に関係なく常に実行(ifの制御外)
正しい書き方: たとえ1行のコードであっても、大括弧を付けて読みやすさと安全性を高めることが推奨されます。
if-else: 2つの選択肢から1つを選ぶ
特徟能: 1つの条件を評価し、条件が真であれば `if` ブロックを、偽であれば `else` ブロックを実行します。
構文テンプレート:
if (ブール式) {
// 条件が true の場合に実行
} else {
// 条件が false の場合に実行
}
コード例:
int age = 17;
if (age >= 18) {
System.out.println("成人です");
} else {
System.out.println("未成年です"); // 出力: 未成年です
}
面接でのポイント: 三項演算子(`条件 ? 式1 : 式2`)は `if-else` の簡易版で、値を返します。
// 三項演算子を使用して上記の if-else と同じ処理を行う
String result = (age >= 18) ? "成人です" : "未成年です";
System.out.println(result); // 出力: 未成年です
注意: 三項演算子は、式1と式2の戻り値が互換性がある場合に使用でき、単純なロジックに適しています。複雑なロジックには `if-else` を使用することをお勧めします。
else if: 複数の条件を評価する
特徴: 複数の条件を順番に評価し、最初に真となる条件に対応するコードブロックを実行し、それ以降の評価を停止します。
構文テンプレート:
if (条件1) {
// 条件1が真の場合に実行
} else if (条件2) {
// 条件1が偽で条件2が真の場合に実行
} else if (条件3) {
// 前の2つの条件が偽で条件3が真の場合に実行
} else {
// すべての条件が偽の場合に実行(オプション)
}
コード例:
int score = 85;
if (score >= 90) {
System.out.println("優秀");
} else if (score >= 80) {
System.out.println("良好"); // 出力: 良好(最初の真の条件が見つかった時点で終了)
} else if (score >= 60) {
System.out.println("合格");
} else {
System.out.println("不合格");
}
一般的な落とし穴: Javaには `elseif` というキーワードは存在せず、`else if` と書く必要があります。
// エラー例: コンパイルエラー
if (a > 10) {
} elseif (a > 5) { // 正しくは else if
}
switch: 複数の値をマッチングする
特徴: 変数の値に基づいて複数の定数をマッチングします。離散値(列挙型、整数、文字列など)の条件判断に適しています。
構文テンプレート(基本版):
switch (変数) {
case 定数1:
// 変数が定数1と一致する場合に実行
break; // switch から抜ける
case 定数2:
// 変数が定数2と一致する場合に実行
break;
default:
// どの定数とも一致しない場合に実行(オプション)
}
サポートされる変数の型:
- 基本型: `byte`, `short`, `int`, `char`
- 参照型: `String`(JDK 7+)、列挙型(`enum`)
コード例1: 基本的な使用法(整数のマッチング):
int week = 3;
switch (week) {
case 1:
System.out.println("月曜日");
break;
case 2:
System.out.println("火曜日");
break;
case 3:
System.out.println("水曜日"); // 出力: 水曜日
break;
default:
System.out.println("他の曜日");
}
コード例2: 文字列のマッチング(JDK 7+):
String day = "Tuesday";
switch (day) {
case "Monday":
System.out.println("月曜日");
break;
case "Tuesday":
System.out.println("火曜日"); // 出力: 火曜日
break;
default:
System.out.println("不明");
}
一般的な落とし穴:
- `break` を忘れると、次の `case` のコードも実行されます。
- JDK 14+ では `yield` を使用して値を返すことができます。
int month = 4;
String season = switch (month) {
case 3, 4, 5 -> { // 複数の値をカンマ区切りで指定
yield "春"; // 値を返す
}
case 6, 7, 8 -> "夏"; // 単一行では yield と大括弧を省略可能
default -> "その他の季節";
};
System.out.println(season); // 出力: 春
2. ループ構造: コードブロックを繰り返し実行する
ループ構造は、特定のコードブロックを繰り返し実行するために使用されます。Java には `while`, `do-while`, `for` の3種類のループがあります。
while: 条件を評価してから実行する
特徴: 条件を評価し、条件が真であればループ体を実行します。
構文テンプレート:
while (ループ条件) {
// 条件が真の場合に実行されるループ体
}
適用場面: ループ回数が不確定で、終了条件がわかっている場合(ファイルの読み込み、ユーザー入力の待機など)。
コード例: ユーザー入力を "exit" まで読み込む
Scanner scanner = new Scanner(System.in);
String input;
// ループ条件: 入力が "exit" でない
while (!"exit".equals(input = scanner.nextLine())) {
System.out.println("あなたは " + input + " を入力しました");
}
System.out.println("プログラム終了");
do-while: 実行してから条件を評価する
特徴: 最初に1回ループ体を実行し、その後条件を評価します。
構文テンプレート:
do {
// ループ体: 少なくとも1回実行
} while (ループ条件); // 注意: 末尾にセミコロンが必要
適用場面: 最初に1回実行する必要がある場合(メニュー駆動、パスワード再試行、初期化チェックなど)。
コード例: パスワード再試行機能
Scanner scanner = new Scanner(System.in);
String password;
do {
System.out.print("パスワードを入力してください: ");
password = scanner.nextLine();
} while (!"123456".equals(password)); // パスワードが誤った場合は再試行
System.out.println("パスワードが正解です");
for: 構造化されたカウントループ
`for` ループは最も柔軟なループ構造であり、カウントループ、イテレーターループ、強化された `for` ループをサポートします。
基本的な for ループ(カウントループ):
構文テンプレート:
for (①初期化; ②ループ条件; ③反復操作) {
④ループ体
}
コード例: 1~5の数字を出力する
for (int i = 1; i <= 5; i++) { // i=1で初期化; 条件i<=5; 各ループ後にi+1
System.out.println(i); // 出力: 1 2 3 4 5
}
強化された for ループ(foreach, JDK 5+):
特徴: 配列やコレクションの反復を簡素化し、インデックスの管理なしに要素を直接取得します。
構文テンプレート:
for (要素型 変数名 : 配列/コレクション) {
// ループ体: 変数名は現在の要素を表す
}
コード例: 配列の反復
int[] nums = {10, 20, 30};
for (int num : nums) { // 配列内の各要素を反復
System.out.println(num); // 出力: 10 20 30
}
一般的な落とし穴: 強化された for ループでは、要素自体やコレクションの構造を変更することはできません。
// エラー例: 基本型の要素を変更しようとする(無効)
for (int num : nums) {
num = 0; // 一時変数のみ変更され、元の配列は変更されない
}
System.out.println(nums[0]); // 依然として 10
イテレーターループ(コレクションの反復):
イテレーター(`Iterator`)を使用してコレクションを反復し、ループ内で安全に要素を削除できます。
コード例:
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
Iterator<String> it = list.iterator();
while (it.hasNext()) { // 次の要素があるか確認
String elem = it.next(); // 次の要素を取得
System.out.println(elem);
if ("A".equals(elem)) {
it.remove(); // 現在の要素を安全に削除
}
}
for ループの一般的な落とし穴:
- ループ条件に代入式を使用すると無限ループになる可能性があります。
- 強化された for ループでコレクションを変更すると `ConcurrentModificationException` が発生します。
3. 制御フローを変更するキーワード: `break`, `continue`, `return`
これらのキーワードは、ループや条件分岐内で実行順序を変更するために使用されます。
break: 現在のループまたは switch 文を強制終了する
機能: 現在のループ(`while`, `for`, `do-while`)または `switch` 文を強制終了します。
基本的な使用法: 現在のループを終了する
for (int i = 0; i < 10; i++) {
if (i == 3) {
break; // i=3 のとき、ループを終了
}
System.out.println(i); // 出力: 0 1 2
}
ラベル付き break: 外側のループを終了する: ラベル(`ラベル名:`)を使用して外側のループを終了することができます。
// ラベル out で外側のループをマーク
out: for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
break out; // 外側のループを終了
}
System.out.println(i + "," + j);
}
}
// 出力: 0,0 0,1 0,2 1,0
continue: 今回のループの残りをスキップする
機能: 現在のループの残りの部分をスキップし、次のループの判定に進みます。
基本的な使用法: 今回のループの残りをスキップする
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) { // i が偶数の場合
continue; // 今回のループの残りをスキップ
}
System.out.println(i); // 出力: 1 3
}
ラベル付き continue: 外側のループの次の反復に進む: 外側のループの次の反復に進みます。
out: for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == 1) {
continue out; // 外側のループの次の反復に進む(i+1)
}
System.out.println(i + "," + j);
}
}
// 出力: 0,0 1,0 2,0
return: メソッドの終了
機能: 現在のメソッドの実行を即座に終了し、メソッド呼び出し元に戻ります。メソッドに戻り値がある場合は、その値を返します。
コード例1: 戻り値がないメソッド:
public static void printNum(int num) {
if (num < 0) {
return; // メソッドを終了
}
System.out.println(num);
}
// 呼び出し
printNum(-1); // 出力なし(メソッドが早期終了)
コード例2: 戻り値があるメソッド:
public static int add(int a, int b) {
return a + b; // 計算結果を返し、メソッドを終了
}
特殊な場面: `main` メソッドで `return` を使用すると、プログラムが終了します。
public static void main(String[] args) {
System.out.println("開始");
return; // プログラムを終了
// 以下のコードは実行されない
System.out.println("終了");
}