レコード・パターン
レコード・パターンを使用して、値がレコード・クラス・タイプのインスタンスであるかどうかをテストし(レコード・クラスを参照)、該当する場合はそのコンポーネント値に対してパターン・マッチングを再帰的に実行できます。
レコード・パターンの背景情報は、JEP 440を参照してください。
次の例では、obj
が、レコード・パターンPoint(double x, double y)
のPoint
レコードのインスタンスかどうかをテストします:
record Point(double x, double y) {}
static void printAngleFromXAxis(Object obj) {
if (obj instanceof Point(double x, double y)) {
System.out.println(Math.toDegrees(Math.atan2(y, x)));
}
}
また、この例ではx
値とy
値をobj
から直接抽出し、Point
レコードのアクセサ・メソッドを自動的にコールします。
レコード・パターンは、型とレコード・パターン・リスト(空の場合あり)で構成されます。この例で、型はPoint
で、パターン・リストは(double x, double y)
です。
ノート:
null
値はどのレコード・パターンとも一致しません。
次の例は、レコード・パターンではなくタイプ・パターンを使用する点を除き、前の例と同じです:
static void printAngleFromXAxisTypePattern(Object obj) {
if (obj instanceof Point p) {
System.out.println(Math.toDegrees(Math.atan2(p.y(), p.x())));
}
}
汎用レコード
レコード・クラスが汎用の場合、レコード・パターンに明示的に型引数を指定できます。たとえば:
record Box<T>(T t) { }
static void printBoxContents(Box<String> bo) {
if (bo instanceof Box<String>(String s)) {
System.out.println("Box contains: " + s);
}
}
値をパターンのレコード・タイプにキャストできるのであれば、値がパラメータ化されたレコード・タイプのインスタンスであるかどうかをテストでき、未チェック変換は必要ありません。次の例ではコンパイルが行われません:
static void uncheckedConversion(Box bo) {
// error: Box cannot be safely cast to Box<String>
if (bo instanceof Box<String>(var s)) {
System.out.println("String " + s);
}
}
型推論
レコード・パターンのコンポーネント・リストでvar
を使用できます。次の例では、コンパイラによって、パターン変数x
およびy
がdouble
型であることが示されます:
static void printAngleFromXAxis(Object obj) {
if (obj instanceof Point(var x, var y)) {
System.out.println(Math.toDegrees(Math.atan2(y, x)));
}
}
コンパイラは、パターンを受け入れるすべての構文(switch
文、switch
式、instanceof
式)で、レコード・パターンの型引数の型を推論できます。
次の例は、printBoxContents
と等価です。コンパイラは型引数とパターン変数を推論します。Box(var s)
はBox<String>(String s)
と推論されます
static void printBoxContentsAgain(Box<String> bo) {
if (bo instanceof Box(var s)) {
System.out.println("Box contains: " + s);
}
}
ネストされたレコード・パターン
レコード・パターンを別のレコード・パターン内にネストできます:
enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) {}
record ColoredRectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}
static void printXCoordOfUpperLeftPointWithPatterns(ColoredRectangle r) {
if (r instanceof ColoredRectangle(
ColoredPoint(Point(var x, var y), var upperLeftColor),
var lowerRightCorner)) {
System.out.println("Upper-left corner: " + x);
}
}
パラメータ化されたレコードでも同じことをできます。コンパイラは、レコード・パターンの型引数とパターン変数の型を推論します。次の例で、コンパイラはBox(Box(var s))
をBox<Box<String>>(Box(String s))
と推論します。
static void nestedBox(Box<Box<String>> bo) {
// Box(Box(var s)) is inferred to be Box<Box<String>>(Box(var s))
if (bo instanceof Box(Box(var s))) {
System.out.println("String " + s);
}
}