S-JIS[2024-09-22/2025-03-19] 変更履歴
Java23のプリミティブ型のパターンマッチ(プレビュー版)について。
2024/9/17にリリースされたJava23で、プレビュー版として プリミティブ型でパターンマッチが出来るようになった。
プリミティブ型のパターンマッチはJava23〜24ではプレビュー版の機能なので、この機能を使いたい場合はコンパイル時にjavacコマンドに--enable-previewを付ける必要があり、
また、実行時にjavaコマンドに--enable-previewを付ける必要がある。
JShellで試す場合もjshellコマンドに--enable-previewを付ける。
> javac --enable-preview --release 23 Example.java > java --enable-preview Example
> java --enable-preview --source 23 Example.java
(Java16以降の)instanceofでは「if (値 instanceof 型 変数)」のように書くことが出来るが、プリミティブ型も使えるようになった。
int n = 127; if (n instanceof byte b) { System.out.println(b); } else { System.out.println("unmatch"); }
「n instanceof byte」の場合、nがbyteの範囲に収まっているとtrueになる。
-128や127はbyteの範囲内なのでマッチするが、-129や128はbyteの範囲外なのでマッチしない。
普通、「obj instanceof T」は「objがTにキャスト可能かどうか」「objをTとして扱えるかどうか」を判定するのに使う。
それと同じく、「n instanceof byte」は「byteにキャスト可能か」「byteとして扱えるか」と解釈することも出来そうだ。
この場合、nがbyteの範囲に入っているということを意味する。
例えば、byteの範囲外である128をbyteに強制的にキャスト(「(byte)128
」)すると-128になってしまう。
128と-128は違う値なので、これは確かに「byteとして扱えない」と言えるような気がする。
ちなみに、「n instanceof byte」は、コンパイルするとExactConversionsSupport.isIntToByteExact()の呼び出しになっている。
ExactConversionsSupportはJava23で新設されたクラスで、isIntToByteExactメソッドは以下のようになっている。
public static boolean isIntToByteExact(int n) { return n == (int)(byte)n; }
(Java21以降の)switchでは「case Integer i」のように書くことが出来るが、プリミティブ型も指定できるようになった。
long value = 128; String type = switch (value) { case byte _ -> "byte"; case short _ -> "short"; case int _ -> "int"; case long _ -> "long"; }; System.out.printf("%d in %s%n", value, type);
「case 型 変数」なので変数は省略できないが、変数を使わない場合はアンダースコア「_」にしておけばいい。
「case byte」は、byteの範囲に収まっているとき(-128〜127のとき)にマッチする。
for (int i = 0; i < 10; i++) { String s = switch (i) { case 0 -> "nothing"; case 1 -> "one"; case 2 -> "two"; case 3 -> "three"; case int n -> "many (%d)".formatted(n); }; System.out.println(s); }
int iに対して「switch(i)」の場合、「case int n」は全ての値とマッチする。
意味合いは「default」と同じだが、defaultとは違い、そのときの値を変数で受け取ることが出来る。
for (int i = 1; i <= 20; i++) { String s = switch (i) { case int n when n % 15 == 0 -> "FizzBuzz"; case int n when n % 3 == 0 -> "Fizz"; case int n when n % 5 == 0 -> "Buzz"; case int n -> Integer.toString(n); }; System.out.println(s); }