PR

Java:instanceof演算子のパターンマッチング機能を1分で

Java

Java 16で正式に導入された、instanceof演算子パターンマッチング機能(Pattern Matching for instanceof)は、型チェックとキャストを一括で処理できる構文です。コードをよりシンプルかつ安全に書くための機能ですが、仕組みや使い方に戸惑う方も多いかもしれません。

このページではパターンマッチング機能について1からわかりやすく解説します。

スポンサーリンク

従来のinstanceofでの判定とキャスト

Java 15以前では、あるオブジェクトが特定の型かを判定し、それを利用しようとする場合、次のように「判定 → キャスト」の2段階を踏むのが一般的でした。

Object obj = "Hello World"; // ここでは実際は String 型

if (obj instanceof String) {
    // まず instanceof で判定
    String s = (String) obj; // キャストを明示的に書く
    System.out.println(s.toUpperCase());
}
  1. if (obj instanceof String) で型チェック (String型かどうか)
  2. String s = (String) obj; でキャスト
  3. s.toUpperCase() のようにメソッド呼び出し

このように、判定とキャストがそれぞれ別々の箇所に存在し、キャストが常に明示的に必要という点がやや煩わしいところでした。

パターンマッチング付きinstanceofの基本構文

Java 16以降では、上記処理をより簡潔に記述できるようになりました。

Object obj = "Hello World";

if (obj instanceof String s) {
    // 'instanceof String s' で判定とキャストを同時に行う
    System.out.println(s.toUpperCase());
}

この書き方では、

  • obj instanceof String s が「パターン」にあたります。
    • String s と書くことで、objString型の場合に、自動的にその型で扱うための変数 s を用意してくれます。
    • 実際には(String)objをする必要がなくなり、冗長なキャストが省略できます。
  • objString型でない場合はif文の条件がfalseとなるので、ブロック内部は実行されません。

パターンマッチング機能のメリット

  1. コードがスッキリ
    • 従来のように毎回キャストを書く必要がなくなり、可読性が向上します。
  2. スコープの明確化
    • sという変数はifブロック内のみ有効になるため、意図しない範囲で使われる可能性がありません。
  3. 安全性の向上
    • instanceofの結果がtrueだった場合だけパターン変数が使えるので、ClassCastExceptionのリスクを意識しなくて済みます。

パターン変数のスコープと使い方

パターンマッチングを行った変数(上の例だと s)の有効範囲(スコープ)は、instanceofのチェックが行われたブロック内に限られます。↓のコードを見てみましょう。

Object obj = "Hello World";

if (obj instanceof String s) {
    // ここでは s は String 型として使える
    System.out.println("Upper case: " + s.toUpperCase());
} else {
    // ここでは s は使えない
    // System.out.println(s.toLowerCase()); // コンパイルエラーになる
}
  • ifブロック内では、変数sString型として使用できます。
  • elseブロックやifブロックを抜けた後では、sは「存在しない」扱いなので使用できません。

これは一見不便に思えるかもしれませんが、「その型だと判明している場所だけでしか使わない」という意図が明確になるため、可読性と安全性が高まります。

論理演算子(AND/ORなど)と組み合わせる場合

Java 16で導入されたパターンマッチングは、「論理演算子」と組み合わせて書く場合が特に強力です。よくある例として、&&(AND)を使って条件がtrueになった場合のみ追加チェックをしたいケースがあります。

Object obj = "Hello World";

if (obj instanceof String s && !s.isEmpty()) {
    // obj が String にマッチし、かつ s が空文字列ではない場合
    System.out.println("Lower case: " + s.toLowerCase());
}
  • obj instanceof String strueのときだけ変数 sString型として扱える
  • その結果をさらに使って !s.isEmpty() をチェック

ここでのポイントは、instanceoftrueでないと&&の右側は評価されない(短絡評価)ため、sを安全に使うことができます。
また、左側がfalseの場合は右側にたどり着かないので、そもそもStringとしての操作が行われず、ClassCastExceptionなどの心配もありません。

なぜ「パターンマッチング」と呼ばれるのか

「パターンマッチング」という用語は、たとえばScalaやKotlinなどではmatch式やwhen式として、型や値のパターンをマッチさせて分岐処理を簡潔に記述できる機能を指します。Javaのinstanceofへの拡張は「パターンマッチングを導入する」流れの一部で、将来的にはswitch文などでもパターンマッチングを活用できる機能が拡充されています(Java 17以降でプレビュー機能として提供)。

instanceof String s は、

  • 「もし objString型というパターンにマッチしたならば」
  • 「そのマッチ対象を s という変数として使えるようにする」

という発想で書かれています。これが「パターンマッチング」と呼ばれる理由です。

実際の利用パターン例

if-else if-else構文との併用

複数の型の可能性をチェックするケースも、よりスマートに書けます。

Object obj = Integer.valueOf(100);

if (obj instanceof String s) {
    System.out.println("It's a String: " + s.toUpperCase());
} else if (obj instanceof Integer i) {
    System.out.println("It's an Integer: " + (i + 10));
} else {
    System.out.println("Unknown type.");
}

objがそれぞれどの型にマッチしたかで場合分けできますし、マッチしたブロック内では常に該当の型として安全に操作できます。

ネストした条件分岐

パターン変数が使えるのは、そのif文や、論理演算子でつながった同一の評価式内になります。

Object obj = "Nested Checking";

if (obj instanceof String s) {
    if (s.length() > 5) {
        System.out.println("String is more than 5 characters");
    }
}

このようにネストしていくことも可能ですが、論理演算子(&&||)を使ってまとめて書く方法も便利です。

まとめ instanceof演算子のパターンマッチング機能

  1. 従来の方法(Java 15以前)
    • instanceofで型をチェック → 明示的にキャスト → キャストした変数で操作
    • コードがやや冗長で、スコープが広くなる場合もある。
  2. 新しいパターンマッチング(Java 16以降)
    • if (obj instanceof String s) という書き方で、型チェックとキャストを一括処理
    • 余計なキャストが不要で、読みやすくなる。
    • 変数 s のスコープがifブロックの中だけに限定され、安全性と可読性が向上。
  3. スコープ & 論理演算子
    • パターン変数 s は、判定したブロックや論理演算子で接続されている範囲内だけ有効。
    • &&|| と組み合わせると、追加の条件式ともスムーズに組み合わせて書ける。
  4. 今後の拡張
    • Java 17以降ではswitch文など、さらに複雑な「パターンマッチング」が徐々に導入(プレビュー)されている。
    • Java言語全体として、他のモダン言語のように「マッチした型や条件に応じた分岐処理を簡潔に書ける」方向へ進化している。

Java 16以降を使える環境であれば、このパターンマッチングを活用してみることをおすすめします。条件分岐やキャスト周りのコードが大幅にシンプルになり、可読性と保守性が向上するはずです。ぜひ活用してみてください!

タイトルとURLをコピーしました