コンテンツにスキップ

Java/基礎/条件分岐

出典: フリー教科書『ウィキブックス(Wikibooks)』

条件分岐

[編集]

概要

[編集]

条件分岐は、プログラムの実行フローを制御する基本的な構造の1つです。この章では、Javaにおける以下の条件分岐の仕組みを解説します:

  • if-else文による基本的な条件分岐
  • switch文による複数条件の分岐
  • switch式による値を返す条件分岐
  • 論理演算子を使用した条件の組み合わせ
  • 三項演算子による簡潔な条件分岐
  • パターンマッチングによる型に基づく分岐

基本的な条件分岐:if-else文

[編集]

構文

[編集]

if-else文の基本構文は以下の通りです:

if (条件式) {
    // 条件が真の場合の処理
} else {
    // 条件が偽の場合の処理
}

複数条件の判定

[編集]

複数の条件を判定する場合は、else if を使用します:

if (条件式1) {
    // 条件1が真の場合の処理
} else if (条件式2) {
    // 条件2が真の場合の処理
} else {
    // いずれの条件も偽の場合の処理
}

実践例

[編集]
public class IfElseExample {
    public static void main(String[] args) {
        var n = 0.0 / 0.0;

        if (n < 0.0) {
            System.out.println("負の数です");
        } else if (n > 0.0) {
            System.out.println("正の数です。");
        } else if (n == 0.0) {
            System.out.println("零です。");
        } else {
            System.out.println(n + "です。");
        }
    }
}

複数条件の分岐:switch文

[編集]

基本構文

[編集]

switch文は、1つの値に基づいて複数の分岐を行う場合に使用します:

switch () {
    case 値1:
        // 値1の場合の処理
        break;
    case 値2:
        // 値2の場合の処理
        break;
    default:
        // どの値にも一致しない場合の処理
        break;
}

文字列による分岐例

[編集]
String fruit = "りんご";
switch (fruit) {
    case "りんご":
    case "バナナ":
    case "いちご":
        System.out.println(fruit + "は果物です");
        break;
    default:
        System.out.println(fruit + "は果物ではありません");
        break;
}

enum型による分岐例

[編集]
enum Animal { DOG, CAT, BIRD }

Animal pet = Animal.DOG;
switch (pet) {
    case DOG:
        System.out.println("ワンワン");
        break;
    case CAT:
        System.out.println("ニャー");
        break;
    case BIRD:
        System.out.println("ピヨピヨ");
        break;
}

値を返す条件分岐:switch式

[編集]

基本構文

[編集]

Java 12以降で導入されたswitch式は、条件分岐の結果を値として返すことができます:

var result = switch () {
    case 値1 -> 返り値1;
    case 値2 -> 返り値2;
    default -> デフォルト値;
};

実践例

[編集]
String fruit = "りんご";
int score = switch (fruit) {
    case "りんご", "バナナ", "いちご" -> 1;
    case "メロン", "スイカ" -> 2;
    default -> 0;
};

条件の組み合わせ:論理演算子

[編集]

主な論理演算子

[編集]
演算子 意味
&& 論理積(AND) A && B
|| 論理和(OR) A || B
! 論理否定(NOT) !A
== 等価 A == B
!= 不等価 A != B

真理値表

[編集]
論理演算子の真理値表
A B !A A && B A || B
false false true false false
false true true false true
true false false false true
true true false true true

この表では、AとBがそれぞれ真(true)または偽(false)の場合に対する、NOT、AND、ORの結果が示されています。

簡潔な条件分岐:三項演算子

[編集]

構文

[編集]
結果 = 条件式 ? 真の場合の値 : 偽の場合の値;

実践例

[編集]
int a = 5, b = 10;
int max = a > b ? a : b;  // より大きい値を選択

パターンマッチングによる型判定

[編集]

instanceofによるパターンマッチング

[編集]

Java 16以降で導入された新しい構文:

if (obj instanceof String str) {
    System.out.println(str.toUpperCase());
}

switchでのパターンマッチング

[編集]

Java 21以降で導入された新機能:

String formatted = switch (obj) {
    case Integer i -> "整数: " + i;
    case String s -> "文字列: " + s;
    case null -> "null値";
    default -> "その他: " + obj;
};

パターンマッチングのキャプチャー

[編集]

キャプチャーとは

[編集]

パターンマッチングにおけるキャプチャーとは、マッチしたパターンの値を変数に代入して再利用できるようにする機能です。これにより、型チェックとキャストを1つの操作で安全に行うことができます。

キャプチャー変数のスコープ

[編集]

キャプチャー変数は、パターンマッチングが成功した場合にのみ使用可能です:

if (obj instanceof String s && s.length() > 0) {
    // このスコープでsを使用可能
    System.out.println(s.toUpperCase());
}
// このスコープではsは使用不可

ガード条件でのキャプチャー

[編集]

キャプチャー変数は、パターンマッチングのガード条件内でも使用できます:

public record Point(int x, int y) {}

void processPoint(Object obj) {
    if (obj instanceof Point p && p.x() > 0 && p.y() > 0) {
        // 正の座標の場合の処理
        System.out.println("正の座標: " + p);
    }
}

switch式でのキャプチャー

[編集]

switch式でもキャプチャーを使用できます:

String describe(Object obj) {
    return switch (obj) {
        case String s when s.length() > 0 -> 
            "非空の文字列: " + s;
        case String s -> 
            "空の文字列";
        case Integer i when i > 0 -> 
            "正の整数: " + i;
        case Integer i -> 
            "0または負の整数: " + i;
        case null -> 
            "null値";
        default -> 
            obj.toString();
    };
}

ネストされたパターンでのキャプチャー

[編集]

複雑なデータ構造でもパターンマッチングとキャプチャーを組み合わせることができます:

record Person(String name, Address address) {}
record Address(String street, String city) {}

void processPerson(Object obj) {
    if (obj instanceof Person p 
        && p.address() instanceof Address a 
        && a.city().equals("東京")) {
        // 東京在住の人の処理
        System.out.println(p.name() + "さんは東京在住です");
    }
}

キャプチャーの利点

[編集]
利点 説明
型安全性 コンパイル時の型チェックにより、型関連のエラーを防ぐ
コードの簡潔さ 型チェックとキャストを1行で行える
可読性 意図が明確で理解しやすいコードになる
スコープの制限 変数の使用範囲が適切に制限される

キャプチーにおける注意点

[編集]
  • キャプチャー変数は、パターンマッチングが成功した場合にのみ初期化される
  • 同じスコープ内で既存の変数名と競合してはいけない
  • switch式では、各caseブランチで異なるキャプチャー変数を使用できる
  • ガード条件(when節)内でもキャプチャー変数を使用可能

パターンマッチングとキャプチャーの組み合わせ例

[編集]
sealed interface Shape permits Circle, Rectangle {
    double area();
}
record Circle(double radius) implements Shape {
    public double area() { return Math.PI * radius * radius; }
}
record Rectangle(double width, double height) implements Shape {
    public double area() { return width * height; }
}

String describeShape(Shape shape) {
    return switch (shape) {
        case Circle c when c.radius() > 10 -> 
            "大きな円(半径: " + c.radius() + ")";
        case Circle c -> 
            "円(半径: " + c.radius() + ")";
        case Rectangle r when r.width() == r.height() -> 
            "正方形(辺長: " + r.width() + ")";
        case Rectangle r -> 
            "長方形(幅: " + r.width() + ", 高さ: " + r.height() + ")";
    };
}

補足

[編集]

パターンマッチングの種類

[編集]
パターン 説明
型パターン 型の一致を確認 case String s
nullパターン null値の確認 case null
リテラルパターン 具体的な値との一致 case 42
列挙型パターン 列挙型の値との一致 case Color.RED
デコンストラクタパターン オブジェクトの構造分解 case Point(int x, int y)