8 パターン・マッチング

パターン・マッチングでは、オブジェクトに特定の構造があるかどうかをテストし、一致がある場合には、そのオブジェクトからデータを抽出します。これはJavaでも実行できることです。ただし、パターン・マッチングには新しい言語拡張が導入されており、より簡潔で強力なコードを使用してオブジェクトから条件付きでデータを抽出できます。

パターンは、値に対して実行できるテストを示します。パターンは文および式のオペランドとして出現し、テストする値を提供します。たとえば、次の式について考えてみます:

s instanceof Rectangle r

パターンRectangle rは、instanceof式のオペランドです。引数sの型がパターンで指定したもの(Rectangle)かどうかをテストします。パターンがテストする引数をターゲットと呼ぶことがあります。

ノート:

前の例のように、instanceofの右側のオペランドがパターンの場合、instanceofパターン一致演算子です。

instanceofの右側のオペランドが型の場合、instanceof型比較演算子です。次の例では、instanceofを型比較演算子として使用します:

s instanceof Rectangle

パターンは、ゼロ個以上のパターン変数を宣言できます。たとえば、パターンRectangle rrを1つのみ宣言します。

パターンに対して値をテストするプロセスはパターン・マッチングと呼ばれます。値がパターンに正常に一致した場合、パターン変数はターゲットのデータで初期化されます。この例では、sRectangleの場合、sRectangleに変換され、rに割り当てられます。

パターンは、switch文または式のcaseラベルでも使用できます。たとえば:

public static double getArea(Shape s) throws IllegalArgumentException {
    switch (s) {
        case Rectangle r:
            return r.length() * r.width();
        case Circle c:
            return c.radius() * c.radius() * Math.PI;
        default:
            throw new IllegalArgumentException("Unrecognized shape");
    }
}

型パターンは、型と1つのパターン変数で構成されます。この例では、Rectangle rが型パターンです。

レコード・パターンは、レコード型とレコード・パターン・リスト(空の場合あり)で構成されます。たとえば、次のレコード宣言と式について考えてみます:

record Point(double x, double y) {}
// ...

obj instanceof Point(double a, double b)

レコード・パターンPoint(double x, double y)は、ターゲットobjPoint(double, double)かどうかをテストします。Point(double, double)である場合、objからxおよびy値を直接抽出し、パターン変数aおよびbにそれぞれ割り当てます。