JEP 405 "Record Patterns (Preview)"が、JDK 19のProposed to TargetからTargetedへの昇格を果たした。Project Amberの傘下にあるこのJEPは、レコード値を分解するレコードパターン(record pattern)による言語の拡張を提案する。レコードパターンは型パターン(type pattern)と併用することで、"堅牢で宣言的、かつ構成可能な形式のデータナビゲーションとプロセッシングを可能にする"が、現時点ではまだプレビュー機能に留まっている。
JDK 16で提供されたJEP 394 "Pattern Matching for instanceof"は、instanceof
演算子を拡張して、型パターンの指定やパターンマッチングの実行を可能にしたものだ。次の例を見てほしい。
public void print(Object o) {
if (o instanceof Double) {
Double d = (Double) o;
System.out.println("d = " + d);
}
}
パターンマッチングを使えば、上のコードを次のように書き換えることができる。
public void print(Object o) {
if (o instanceof Double d) {
System.out.println("d = " + d);
}
}
上のコードでは、実行時のo
の値がDouble
のインスタンスであれば、o
は型パターンDouble d
にマッチする。これによって明示的な型キャストが不要になり、コードがより短く、管理性の高いものになる。
JEP 395 "Records"は、データの透過的キャリアであるRecordクラスを導入することにより、不変(immutable)オブジェクトを簡単に記述できるようにするものだ。次の例を見てほしい。
record Point(int x, int y) { }
ここでは、コンストラクタやアクセッサメソッド、その他toString()
やhashCode()
といったメソッドを明示的に記述する必要がなくなり、コードがクリーンで冗長性が低いものになっている。
レコードクラスのインスタンスがコードブロック内で使用される場合、通常はアクセッサメソッドを使ってデータを取得する。例えば、
public void printSum(Object o) {
if (o instanceof Point p) {
int x = p.x();
int y = p.y();
System.out.println(x + y);
}
}
上のコードでは、パターン変数p
を使ってアクセッサメソッドx()
とy()
を実行することで、x
とy
の値を取得している。それ以外、p
は使用されていない。レコードパターンであれば、変数p
の必要はなく、
上のコードを次のように書き直すことができる。
public void printSum(Object o) {
if (o instanceof Point(int x int y)) {
System.out.println(x + y);
}
}
同じような方法で、もっと複雑なオブジェクトグラフを分解することも可能だ。以下のコード例を見てほしい。
enum Color {RED, GREEN, BLUE}
record ColoredPoint(Point p, Color color) {}
record Point(int x, int y) {}
record Square(ColoredPoint upperLeft, ColoredPoint lowerRight) {}
レコードパターンを使ったパターンマッチングのシナリオで、左上(upperLeft)のColorPoint
を表示する必要のある場合は、次のように分解することができる。
public void printUpperLeftColoredPoint(Square s) {
if (s instanceof Square(ColoredPoint(Point(var x, var y), var color), var leftRight))){
}
}
上のような分解を使用しないとすれば、コードはもっと冗長なものになる。
さらに型パターンは、JEP 406 "Pattern Matching for switch (Preview)"(JDK 17で提供)、およびJEP 420 "Pattern Matching for switch (Second Preview)"(JDK 18で提供)を通じて、switch
のcaseラベルとして使用できるように拡張されている。これらにより、同じような分解をswitch
文でも使うことができるようになる。ただし、このJEPは現在も検討中であるため、さまざまな方向に展開され、拡張される可能性がある。興味のある開発者は、メーリングリストを見たり、ディスカッションに参加したりするとよいだろう。